diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000000..eddb447a20e --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Formatting code base +19ab5e34677a7fea521b682ee35c974f7aaac0fb diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 881f66b67b5..dba7c4eef0b 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -36,5 +36,5 @@ jobs: license_header_check_enabled: false unacceptable_language_check_enabled: false api_breakage_check_enabled: false - format_check_enabled: false + format_check_enabled: true shell_check_enabled: false diff --git a/.swift-format b/.swift-format new file mode 100644 index 00000000000..3d02fb82cfb --- /dev/null +++ b/.swift-format @@ -0,0 +1,13 @@ +{ + "version": 1, + "lineLength": 10000, + "indentation": { + "spaces": 4 + }, + "lineBreakBeforeEachArgument": true, + "maximumBlankLines" : 1, + "multiElementCollectionTrailingCommas" : true, + "rules": { + }, + "tabWidth": 4 +} diff --git a/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift b/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift index 09460dbd7e5..f8cf86007cb 100644 --- a/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift +++ b/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift @@ -1,18 +1,17 @@ -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import Basics +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import Basics import Benchmark import Foundation import PackageModel -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import func PackageGraph.loadModulesGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import func PackageGraph.loadModulesGraph import Workspace let benchmarks = { let defaultMetrics: [BenchmarkMetric] if let envVar = ProcessInfo.processInfo.environment["SWIFTPM_BENCHMARK_ALL_METRICS"], - envVar.lowercased() == "true" || envVar == "1" { + envVar.lowercased() == "true" || envVar == "1" + { defaultMetrics = .all } else { defaultMetrics = [ @@ -23,7 +22,8 @@ let benchmarks = { let modulesGraphDepth: Int if let envVar = ProcessInfo.processInfo.environment["SWIFTPM_BENCHMARK_MODULES_GRAPH_DEPTH"], - let parsedValue = Int(envVar) { + let parsedValue = Int(envVar) + { modulesGraphDepth = parsedValue } else { modulesGraphDepth = 150 @@ -31,7 +31,8 @@ let benchmarks = { let modulesGraphWidth: Int if let envVar = ProcessInfo.processInfo.environment["SWIFTPM_BENCHMARK_MODULES_GRAPH_WIDTH"], - let parsedValue = Int(envVar) { + let parsedValue = Int(envVar) + { modulesGraphWidth = parsedValue } else { modulesGraphWidth = 150 @@ -39,7 +40,8 @@ let benchmarks = { let packagesGraphDepth: Int if let envVar = ProcessInfo.processInfo.environment["SWIFTPM_BENCHMARK_PACKAGES_GRAPH_DEPTH"], - let parsedValue = Int(envVar) { + let parsedValue = Int(envVar) + { packagesGraphDepth = parsedValue } else { packagesGraphDepth = 10 @@ -103,8 +105,8 @@ let benchmarks = { ) ) { benchmark in try syntheticModulesGraph( - benchmark, - modulesGraphDepth: modulesGraphDepth, + benchmark, + modulesGraphDepth: modulesGraphDepth, modulesGraphWidth: modulesGraphWidth, includeMacros: true ) @@ -112,9 +114,9 @@ let benchmarks = { } func syntheticModulesGraph( - _ benchmark: Benchmark, - modulesGraphDepth: Int, - modulesGraphWidth: Int, + _ benchmark: Benchmark, + modulesGraphDepth: Int, + modulesGraphWidth: Int, includeMacros: Bool = false ) throws { // If macros are included, modules are split in three parts: @@ -137,9 +139,12 @@ func syntheticModulesGraph( let macrosDependenciesModules: [TargetDescription] if includeMacros { macrosModules = try (0.. swift package update ``` -Alternatively, if you are using Xcode, you can update to the latest version of all packages: +Alternatively, if you are using Xcode, you can update to the latest version of all packages: **Xcode App** > *File* > *Swift Packages* > *Update to Latest Package Versions* diff --git a/Examples/package-info/Package.swift b/Examples/package-info/Package.swift index 3fcc7509b5a..921001a67a3 100644 --- a/Examples/package-info/Package.swift +++ b/Examples/package-info/Package.swift @@ -6,11 +6,11 @@ let package = Package( name: "package-info", platforms: [ .macOS(.v13), - .iOS(.v13) + .iOS(.v13), ], dependencies: [ // This just points to the SwiftPM at the root of this repository. - .package(name: "swift-package-manager", path: "../../"), + .package(name: "swift-package-manager", path: "../../") // You will want to depend on a stable semantic version instead: // .package(url: "https://github.com/swiftlang/swift-package-manager", .exact("0.4.0")) ], @@ -20,6 +20,6 @@ let package = Package( dependencies: [ .product(name: "SwiftPM", package: "swift-package-manager") ] - ), + ) ] ) diff --git a/Package.swift b/Package.swift index aa32ba1e384..c63908d3b02 100644 --- a/Package.swift +++ b/Package.swift @@ -20,16 +20,20 @@ import PackageDescription let swiftpmLinkSettings: [LinkerSetting] let packageLibraryLinkSettings: [LinkerSetting] if let resourceDirPath = ProcessInfo.processInfo.environment["SWIFTCI_INSTALL_RPATH_OS"] { - swiftpmLinkSettings = [.unsafeFlags([ - "-no-toolchain-stdlib-rpath", - "-Xlinker", "-rpath", - "-Xlinker", "$ORIGIN/../lib/swift/\(resourceDirPath)", - ])] - packageLibraryLinkSettings = [.unsafeFlags([ - "-no-toolchain-stdlib-rpath", - "-Xlinker", "-rpath", - "-Xlinker", "$ORIGIN/../../\(resourceDirPath)", - ])] + swiftpmLinkSettings = [ + .unsafeFlags([ + "-no-toolchain-stdlib-rpath", + "-Xlinker", "-rpath", + "-Xlinker", "$ORIGIN/../lib/swift/\(resourceDirPath)", + ]) + ] + packageLibraryLinkSettings = [ + .unsafeFlags([ + "-no-toolchain-stdlib-rpath", + "-Xlinker", "-rpath", + "-Xlinker", "$ORIGIN/../../\(resourceDirPath)", + ]) + ] } else { swiftpmLinkSettings = [] packageLibraryLinkSettings = [] @@ -37,15 +41,15 @@ if let resourceDirPath = ProcessInfo.processInfo.environment["SWIFTCI_INSTALL_RP // Common experimental flags to be added to all targets. let commonExperimentalFeatures: [SwiftSetting] = [ - .enableExperimentalFeature("MemberImportVisibility"), + .enableExperimentalFeature("MemberImportVisibility") ] // Certain targets fail to compile with MemberImportVisibility enabled on 6.0.3 // but work with >=6.1. These targets opt in to using `swift6CompatibleExperimentalFeatures`. #if swift(>=6.1) -let swift6CompatibleExperimentalFeatures = commonExperimentalFeatures + let swift6CompatibleExperimentalFeatures = commonExperimentalFeatures #else -let swift6CompatibleExperimentalFeatures: [SwiftSetting] = [] + let swift6CompatibleExperimentalFeatures: [SwiftSetting] = [] #endif /** SwiftPMDataModel is the subset of SwiftPM product that includes just its data model. @@ -84,14 +88,14 @@ let swiftPMProduct = ( ) #if os(Windows) -let includeDynamicLibrary: Bool = false -let systemSQLitePkgConfig: String? = nil + let includeDynamicLibrary: Bool = false + let systemSQLitePkgConfig: String? = nil #else -let includeDynamicLibrary: Bool = true -var systemSQLitePkgConfig: String? = "sqlite3" -if ProcessInfo.processInfo.environment["SWIFTCI_INSTALL_RPATH_OS"] == "android" { - systemSQLitePkgConfig = nil -} + let includeDynamicLibrary: Bool = true + var systemSQLitePkgConfig: String? = "sqlite3" + if ProcessInfo.processInfo.environment["SWIFTCI_INSTALL_RPATH_OS"] == "android" { + systemSQLitePkgConfig = nil + } #endif /** An array of products which have two versions listed: one dynamically linked, the other with the @@ -116,13 +120,13 @@ if shouldUseSwiftBuildFramework { .product(name: "SwiftDriver", package: "swift-driver") ] swiftTSCBasicsDeps = [ - .product(name: "TSCBasic", package: "swift-tools-support-core"), + .product(name: "TSCBasic", package: "swift-tools-support-core") ] swiftToolsCoreSupportAutoDeps = [ .product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core") ] swiftTSCTestSupportDeps = [ - .product(name: "TSCTestSupport", package: "swift-tools-support-core"), + .product(name: "TSCTestSupport", package: "swift-tools-support-core") ] } let package = Package( @@ -133,56 +137,56 @@ let package = Package( .macCatalyst(.v17), ], products: - autoProducts.flatMap { - (includeDynamicLibrary ? [ + autoProducts.flatMap { + (includeDynamicLibrary + ? [ + .library( + name: $0.name, + type: .dynamic, + targets: $0.targets + ) + ] : []) + + [ + .library( + name: "\($0.name)-auto", + targets: $0.targets + ) + ] + } + [ + .library( + name: "XCBuildSupport", + targets: ["XCBuildSupport"] + ), .library( - name: $0.name, + name: "PackageDescription", type: .dynamic, - targets: $0.targets + targets: ["PackageDescription", "CompilerPluginSupport"] ), - ] : []) - + - [ .library( - name: "\($0.name)-auto", - targets: $0.targets + name: "AppleProductTypes", + type: .dynamic, + targets: ["AppleProductTypes"] ), - ] - } + [ - .library( - name: "XCBuildSupport", - targets: ["XCBuildSupport"] - ), - .library( - name: "PackageDescription", - type: .dynamic, - targets: ["PackageDescription", "CompilerPluginSupport"] - ), - .library( - name: "AppleProductTypes", - type: .dynamic, - targets: ["AppleProductTypes"] - ), - .library( - name: "PackagePlugin", - type: .dynamic, - targets: ["PackagePlugin"] - ), - .library( - name: "PackageCollectionsModel", - targets: ["PackageCollectionsModel"] - ), - .library( - name: "SwiftPMPackageCollections", - targets: [ - "PackageCollections", - "PackageCollectionsModel", - "PackageCollectionsSigning", - "PackageModel", - ] - ), - ], + .library( + name: "PackagePlugin", + type: .dynamic, + targets: ["PackagePlugin"] + ), + .library( + name: "PackageCollectionsModel", + targets: ["PackageCollectionsModel"] + ), + .library( + name: "SwiftPMPackageCollections", + targets: [ + "PackageCollections", + "PackageCollectionsModel", + "PackageCollectionsSigning", + "PackageModel", + ] + ), + ], targets: [ // The `AppleProductTypes` target provides additional product types // to `Package.swift` manifests. Here we build a debug version of the @@ -196,8 +200,9 @@ let package = Package( swiftSettings: commonExperimentalFeatures + [ .unsafeFlags(["-package-description-version", "999.0"]), .unsafeFlags(["-enable-library-evolution"], .when(platforms: [.macOS])), - .unsafeFlags(["-Xfrontend", "-module-link-name", "-Xfrontend", "AppleProductTypes"]) - ]), + .unsafeFlags(["-Xfrontend", "-module-link-name", "-Xfrontend", "AppleProductTypes"]), + ] + ), .target( name: "SourceKitLSPAPI", @@ -223,7 +228,7 @@ let package = Package( .target( name: "_AsyncFileSystem", dependencies: [ - .product(name: "SystemPackage", package: "swift-system"), + .product(name: "SystemPackage", package: "swift-system") ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ @@ -258,7 +263,7 @@ let package = Package( dependencies: ["Basics"], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -274,7 +279,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -287,7 +292,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -297,7 +302,7 @@ let package = Package( dependencies: ["Basics"], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -305,13 +310,14 @@ let package = Package( /** API for deserializing diagnostics and applying fix-its */ name: "SwiftFixIt", dependencies: [ - "Basics", - ] + swiftTSCBasicsDeps + swiftSyntaxDependencies( - ["SwiftDiagnostics", "SwiftIDEUtils", "SwiftParser", "SwiftSyntax"] - ), + "Basics" + ] + swiftTSCBasicsDeps + + swiftSyntaxDependencies( + ["SwiftDiagnostics", "SwiftIDEUtils", "SwiftParser", "SwiftSyntax"] + ), exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -319,11 +325,11 @@ let package = Package( /** API for inspecting symbols defined in binaries */ name: "BinarySymbols", dependencies: [ - "Basics", + "Basics" ] + swiftTSCBasicsDeps, exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -335,7 +341,7 @@ let package = Package( dependencies: ["Basics"], exclude: ["CMakeLists.txt", "README.md"], swiftSettings: swift6CompatibleExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -349,7 +355,7 @@ let package = Package( ], exclude: ["CMakeLists.txt", "README.md"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -366,7 +372,7 @@ let package = Package( ], exclude: ["CMakeLists.txt", "README.md"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -381,7 +387,7 @@ let package = Package( "CMakeLists.txt", ], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -397,7 +403,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: swift6CompatibleExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -411,7 +417,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -423,7 +429,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -437,7 +443,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -460,7 +466,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), .target( @@ -477,7 +483,7 @@ let package = Package( ] + swiftDriverDeps, exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), .target( @@ -488,7 +494,7 @@ let package = Package( ] + swiftDriverDeps, exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), .target( @@ -501,7 +507,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), .target( @@ -529,7 +535,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), .target( @@ -543,7 +549,7 @@ let package = Package( "PackageSigning", ], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -565,7 +571,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -588,7 +594,7 @@ let package = Package( ] + swiftSyntaxDependencies(["SwiftIDEUtils", "SwiftRefactor"]), exclude: ["CMakeLists.txt", "README.md"], swiftSettings: swift6CompatibleExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -604,7 +610,7 @@ let package = Package( ], exclude: ["CMakeLists.txt", "README.md"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -620,7 +626,7 @@ let package = Package( "PackageModel", ], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -643,7 +649,7 @@ let package = Package( ], exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -799,10 +805,10 @@ let package = Package( "Build", "XCBuildSupport", "SwiftBuildSupport", - "_InternalTestSupport" + "_InternalTestSupport", ], swiftSettings: [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -822,14 +828,14 @@ let package = Package( "Workspace", ] + swiftTSCTestSupportDeps, swiftSettings: [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), .target( /** SwiftPM internal test suite support library */ name: "_IntegrationTestSupport", dependencies: [ - "_InternalTestSupport", + "_InternalTestSupport" ] + swiftTSCTestSupportDeps, ), @@ -838,7 +844,7 @@ let package = Package( name: "tsan_utils", dependencies: [], swiftSettings: [ - .unsafeFlags(["-static"]), + .unsafeFlags(["-static"]) ] ), @@ -996,17 +1002,17 @@ let package = Package( name: "package-info", dependencies: ["Workspace"], path: "Examples/package-info/Sources/package-info" - ) + ), ], swiftLanguageModes: [.v5] ) #if canImport(Darwin) -package.targets.append(contentsOf: [ - .executableTarget( - name: "swiftpm-testing-helper" - ) -]) + package.targets.append(contentsOf: [ + .executableTarget( + name: "swiftpm-testing-helper" + ) + ]) #endif // rdar://101868275 "error: cannot find 'XCTAssertEqual' in scope" can affect almost any functional test, so we flat out @@ -1024,7 +1030,7 @@ if ProcessInfo.processInfo.environment["SWIFTCI_DISABLE_SDK_DEPENDENT_TESTS"] == .executableTarget( name: "dummy-swiftc", dependencies: [ - "Basics", + "Basics" ] ), .testTarget( @@ -1058,19 +1064,18 @@ if ProcessInfo.processInfo.environment["SWIFTCI_DISABLE_SDK_DEPENDENT_TESTS"] == ]) } - func swiftSyntaxDependencies(_ names: [String]) -> [Target.Dependency] { - /// Whether swift-syntax is being built as a single dynamic library instead of as a separate library per module. - /// - /// This means that the swift-syntax symbols don't need to be statically linked, which allows us to stay below the - /// maximum number of exported symbols on Windows, in turn allowing us to build sourcekit-lsp using SwiftPM on Windows - /// and run its tests. - let buildDynamicSwiftSyntaxLibrary = ProcessInfo.processInfo.environment["SWIFTSYNTAX_BUILD_DYNAMIC_LIBRARY"] != nil - if buildDynamicSwiftSyntaxLibrary { - return [.product(name: "_SwiftSyntaxDynamic", package: "swift-syntax")] - } else { - return names.map { .product(name: $0, package: "swift-syntax") } - } + /// Whether swift-syntax is being built as a single dynamic library instead of as a separate library per module. + /// + /// This means that the swift-syntax symbols don't need to be statically linked, which allows us to stay below the + /// maximum number of exported symbols on Windows, in turn allowing us to build sourcekit-lsp using SwiftPM on Windows + /// and run its tests. + let buildDynamicSwiftSyntaxLibrary = ProcessInfo.processInfo.environment["SWIFTSYNTAX_BUILD_DYNAMIC_LIBRARY"] != nil + if buildDynamicSwiftSyntaxLibrary { + return [.product(name: "_SwiftSyntaxDynamic", package: "swift-syntax")] + } else { + return names.map { .product(name: $0, package: "swift-syntax") } + } } // Add package dependency on llbuild when not bootstrapping. @@ -1088,17 +1093,17 @@ let relatedDependenciesBranch = "main" if ProcessInfo.processInfo.environment["SWIFTPM_LLBUILD_FWK"] == nil { if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { package.dependencies += [ - .package(url: "https://github.com/swiftlang/swift-llbuild.git", branch: relatedDependenciesBranch), + .package(url: "https://github.com/swiftlang/swift-llbuild.git", branch: relatedDependenciesBranch) ] } else { // In Swift CI, use a local path to llbuild to interoperate with tools // like `update-checkout`, which control the sources externally. package.dependencies += [ - .package(name: "swift-llbuild", path: "../llbuild"), + .package(name: "swift-llbuild", path: "../llbuild") ] } package.targets.first(where: { $0.name == "SPMLLBuild" })!.dependencies += [ - .product(name: "llbuildSwift", package: "swift-llbuild"), + .product(name: "llbuildSwift", package: "swift-llbuild") ] } @@ -1145,29 +1150,29 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { /// If ENABLE_APPLE_PRODUCT_TYPES is set in the environment, then also define ENABLE_APPLE_PRODUCT_TYPES in each of the regular targets and test targets. if ProcessInfo.processInfo.environment["ENABLE_APPLE_PRODUCT_TYPES"] == "1" { for target in package.targets.filter({ $0.type == .regular || $0.type == .test }) { - target.swiftSettings = (target.swiftSettings ?? []) + [ .define("ENABLE_APPLE_PRODUCT_TYPES") ] + target.swiftSettings = (target.swiftSettings ?? []) + [.define("ENABLE_APPLE_PRODUCT_TYPES")] } } if !shouldUseSwiftBuildFramework { - let swiftbuildsupport: Target = package.targets.first(where: { $0.name == "SwiftBuildSupport" } )! + let swiftbuildsupport: Target = package.targets.first(where: { $0.name == "SwiftBuildSupport" })! swiftbuildsupport.dependencies += [ - .product(name: "SwiftBuild", package: "swift-build"), + .product(name: "SwiftBuild", package: "swift-build") ] swiftbuildsupport.dependencies += [ // This is here to statically link the build service in the same executable as SwiftPM - .product(name: "SWBBuildService", package: "swift-build"), + .product(name: "SWBBuildService", package: "swift-build") ] if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { package.dependencies += [ - .package(url: "https://github.com/swiftlang/swift-build.git", branch: relatedDependenciesBranch), + .package(url: "https://github.com/swiftlang/swift-build.git", branch: relatedDependenciesBranch) ] } else { package.dependencies += [ - .package(path: "../swift-build"), + .package(path: "../swift-build") ] } } diff --git a/Sources/AppleProductTypes/Product.swift b/Sources/AppleProductTypes/Product.swift index 23f52a0a850..be2239e9b65 100644 --- a/Sources/AppleProductTypes/Product.swift +++ b/Sources/AppleProductTypes/Product.swift @@ -11,80 +11,86 @@ @_spi(PackageProductSettings) import PackageDescription #if ENABLE_APPLE_PRODUCT_TYPES -extension Product { - /// Creates an iOS application package product. - /// - /// - Parameters: - /// - name: The name of the application product. - /// - targets: The targets to include in the application product; one and only one of them should be an executable target. - /// - settings: The settings that define the core properties of the application. - public static func iOSApplication( - name: String, - targets: [String], - bundleIdentifier: String? = nil, - teamIdentifier: String? = nil, - displayVersion: String? = nil, - bundleVersion: String? = nil, - iconAssetName: String? = nil, - accentColorAssetName: String? = nil, - supportedDeviceFamilies: [ProductSetting.IOSAppInfo.DeviceFamily], - supportedInterfaceOrientations: [ProductSetting.IOSAppInfo.InterfaceOrientation], - capabilities: [ProductSetting.IOSAppInfo.Capability] = [], - additionalInfoPlistContentFilePath: String? = nil - ) -> Product { - return iOSApplication( - name: name, - targets: targets, - bundleIdentifier: bundleIdentifier, - teamIdentifier: teamIdentifier, - displayVersion: displayVersion, - bundleVersion: bundleVersion, - appIcon: iconAssetName.map({ .asset($0) }), - accentColor: accentColorAssetName.map({ .asset($0) }), - supportedDeviceFamilies: supportedDeviceFamilies, - supportedInterfaceOrientations: supportedInterfaceOrientations, - capabilities: capabilities, - additionalInfoPlistContentFilePath: additionalInfoPlistContentFilePath - ) - } - - /// Creates an iOS application package product. - /// - /// - Parameters: - /// - name: The name of the application product. - /// - targets: The targets to include in the application product; one and only one of them should be an executable target. - /// - settings: The settings that define the core properties of the application. - @available(_PackageDescription, introduced: 5.6) - public static func iOSApplication( - name: String, - targets: [String], - bundleIdentifier: String? = nil, - teamIdentifier: String? = nil, - displayVersion: String? = nil, - bundleVersion: String? = nil, - appIcon: ProductSetting.IOSAppInfo.AppIcon? = nil, - accentColor: ProductSetting.IOSAppInfo.AccentColor? = nil, - supportedDeviceFamilies: [ProductSetting.IOSAppInfo.DeviceFamily], - supportedInterfaceOrientations: [ProductSetting.IOSAppInfo.InterfaceOrientation], - capabilities: [ProductSetting.IOSAppInfo.Capability] = [], - appCategory: ProductSetting.IOSAppInfo.AppCategory? = nil, - additionalInfoPlistContentFilePath: String? = nil - ) -> Product { - return .executable(name: name, targets: targets, settings: [ - bundleIdentifier.map{ .bundleIdentifier($0) }, - teamIdentifier.map{ .teamIdentifier($0) }, - displayVersion.map{ .displayVersion($0) }, - bundleVersion.map{ .bundleVersion($0) }, - .iOSAppInfo(ProductSetting.IOSAppInfo( - appIcon: appIcon, - accentColor: accentColor, + extension Product { + /// Creates an iOS application package product. + /// + /// - Parameters: + /// - name: The name of the application product. + /// - targets: The targets to include in the application product; one and only one of them should be an executable target. + /// - settings: The settings that define the core properties of the application. + public static func iOSApplication( + name: String, + targets: [String], + bundleIdentifier: String? = nil, + teamIdentifier: String? = nil, + displayVersion: String? = nil, + bundleVersion: String? = nil, + iconAssetName: String? = nil, + accentColorAssetName: String? = nil, + supportedDeviceFamilies: [ProductSetting.IOSAppInfo.DeviceFamily], + supportedInterfaceOrientations: [ProductSetting.IOSAppInfo.InterfaceOrientation], + capabilities: [ProductSetting.IOSAppInfo.Capability] = [], + additionalInfoPlistContentFilePath: String? = nil + ) -> Product { + return iOSApplication( + name: name, + targets: targets, + bundleIdentifier: bundleIdentifier, + teamIdentifier: teamIdentifier, + displayVersion: displayVersion, + bundleVersion: bundleVersion, + appIcon: iconAssetName.map({ .asset($0) }), + accentColor: accentColorAssetName.map({ .asset($0) }), supportedDeviceFamilies: supportedDeviceFamilies, supportedInterfaceOrientations: supportedInterfaceOrientations, capabilities: capabilities, - appCategory: appCategory, additionalInfoPlistContentFilePath: additionalInfoPlistContentFilePath - )) - ].compactMap{ $0 }) + ) + } + + /// Creates an iOS application package product. + /// + /// - Parameters: + /// - name: The name of the application product. + /// - targets: The targets to include in the application product; one and only one of them should be an executable target. + /// - settings: The settings that define the core properties of the application. + @available(_PackageDescription, introduced: 5.6) + public static func iOSApplication( + name: String, + targets: [String], + bundleIdentifier: String? = nil, + teamIdentifier: String? = nil, + displayVersion: String? = nil, + bundleVersion: String? = nil, + appIcon: ProductSetting.IOSAppInfo.AppIcon? = nil, + accentColor: ProductSetting.IOSAppInfo.AccentColor? = nil, + supportedDeviceFamilies: [ProductSetting.IOSAppInfo.DeviceFamily], + supportedInterfaceOrientations: [ProductSetting.IOSAppInfo.InterfaceOrientation], + capabilities: [ProductSetting.IOSAppInfo.Capability] = [], + appCategory: ProductSetting.IOSAppInfo.AppCategory? = nil, + additionalInfoPlistContentFilePath: String? = nil + ) -> Product { + return .executable( + name: name, + targets: targets, + settings: [ + bundleIdentifier.map { .bundleIdentifier($0) }, + teamIdentifier.map { .teamIdentifier($0) }, + displayVersion.map { .displayVersion($0) }, + bundleVersion.map { .bundleVersion($0) }, + .iOSAppInfo( + ProductSetting.IOSAppInfo( + appIcon: appIcon, + accentColor: accentColor, + supportedDeviceFamilies: supportedDeviceFamilies, + supportedInterfaceOrientations: supportedInterfaceOrientations, + capabilities: capabilities, + appCategory: appCategory, + additionalInfoPlistContentFilePath: additionalInfoPlistContentFilePath + ) + ), + ].compactMap { $0 } + ) + } } -} #endif diff --git a/Sources/Basics/Archiver/TarArchiver.swift b/Sources/Basics/Archiver/TarArchiver.swift index 2d1c7fce5b2..6663d402c28 100644 --- a/Sources/Basics/Archiver/TarArchiver.swift +++ b/Sources/Basics/Archiver/TarArchiver.swift @@ -37,9 +37,9 @@ public struct TarArchiver: Archiver { self.cancellator = cancellator ?? Cancellator(observabilityScope: .none) #if os(Windows) - self.tarCommand = "tar.exe" + self.tarCommand = "tar.exe" #else - self.tarCommand = "tar" + self.tarCommand = "tar" #endif } @@ -67,13 +67,15 @@ public struct TarArchiver: Archiver { DispatchQueue.sharedConcurrent.async { defer { self.cancellator.deregister(registrationKey) } - completion(.init(catching: { - try process.launch() - let processResult = try process.waitUntilExit() - guard processResult.exitStatus == .terminated(code: 0) else { - throw try StringError(processResult.utf8stderrOutput()) - } - })) + completion( + .init(catching: { + try process.launch() + let processResult = try process.waitUntilExit() + guard processResult.exitStatus == .terminated(code: 0) else { + throw try StringError(processResult.utf8stderrOutput()) + } + }) + ) } } catch { return completion(.failure(error)) @@ -121,11 +123,13 @@ public struct TarArchiver: Archiver { DispatchQueue.sharedConcurrent.async { defer { self.cancellator.deregister(registrationKey) } - completion(.init(catching: { - try process.launch() - let processResult = try process.waitUntilExit() - return processResult.exitStatus == .terminated(code: 0) - })) + completion( + .init(catching: { + try process.launch() + let processResult = try process.waitUntilExit() + return processResult.exitStatus == .terminated(code: 0) + }) + ) } } catch { return completion(.failure(error)) diff --git a/Sources/Basics/Archiver/ZipArchiver.swift b/Sources/Basics/Archiver/ZipArchiver.swift index d4f4f1bb7d2..925b6b8e4d1 100644 --- a/Sources/Basics/Archiver/ZipArchiver.swift +++ b/Sources/Basics/Archiver/ZipArchiver.swift @@ -14,7 +14,7 @@ import Dispatch import struct TSCBasic.FileSystemError #if os(Windows) -import WinSDK + import WinSDK #endif /// An `Archiver` that handles ZIP archives using the command-line `zip` and `unzip` tools. @@ -49,16 +49,16 @@ public struct ZipArchiver: Archiver, Cancellable { self.cancellator = cancellator ?? Cancellator(observabilityScope: .none) #if os(Windows) - var tarPath: PWSTR? - defer { CoTaskMemFree(tarPath) } - let hr = withUnsafePointer(to: FOLDERID_System) { id in - SHGetKnownFolderPath(id, DWORD(KF_FLAG_DEFAULT.rawValue), nil, &tarPath) - } - if hr == S_OK, let tarPath { - windowsTar = String(decodingCString: tarPath, as: UTF16.self) + "\\tar.exe" - } else { - windowsTar = "tar.exe" - } + var tarPath: PWSTR? + defer { CoTaskMemFree(tarPath) } + let hr = withUnsafePointer(to: FOLDERID_System) { id in + SHGetKnownFolderPath(id, DWORD(KF_FLAG_DEFAULT.rawValue), nil, &tarPath) + } + if hr == S_OK, let tarPath { + windowsTar = String(decodingCString: tarPath, as: UTF16.self) + "\\tar.exe" + } else { + windowsTar = "tar.exe" + } #endif } @@ -77,9 +77,9 @@ public struct ZipArchiver: Archiver, Cancellable { } #if os(Windows) - // FileManager lost the ability to detect tar.exe as executable. - // It's part of system32 anyway so use the absolute path. - let process = AsyncProcess(arguments: [windowsTar, "xf", archivePath.pathString, "-C", destinationPath.pathString]) + // FileManager lost the ability to detect tar.exe as executable. + // It's part of system32 anyway so use the absolute path. + let process = AsyncProcess(arguments: [windowsTar, "xf", archivePath.pathString, "-C", destinationPath.pathString]) #else let process = AsyncProcess(arguments: [ self.unzip, archivePath.pathString, "-d", destinationPath.pathString, @@ -91,13 +91,15 @@ public struct ZipArchiver: Archiver, Cancellable { DispatchQueue.sharedConcurrent.async { defer { self.cancellator.deregister(registrationKey) } - completion(.init(catching: { - try process.launch() - let processResult = try process.waitUntilExit() - guard processResult.exitStatus == .terminated(code: 0) else { - throw try StringError(processResult.utf8stderrOutput()) - } - })) + completion( + .init(catching: { + try process.launch() + let processResult = try process.waitUntilExit() + guard processResult.exitStatus == .terminated(code: 0) else { + throw try StringError(processResult.utf8stderrOutput()) + } + }) + ) } } catch { return completion(.failure(error)) @@ -113,35 +115,35 @@ public struct ZipArchiver: Archiver, Cancellable { } #if os(Windows) - let process = AsyncProcess( - // FIXME: are these the right arguments? - arguments: [windowsTar, "-a", "-c", "-f", destinationPath.pathString, directory.basename], - workingDirectory: directory.parentDirectory - ) + let process = AsyncProcess( + // FIXME: are these the right arguments? + arguments: [windowsTar, "-a", "-c", "-f", destinationPath.pathString, directory.basename], + workingDirectory: directory.parentDirectory + ) #elseif os(FreeBSD) - // On FreeBSD, the unzip command is available in base but not the zip command. - // Therefore; we use libarchive(bsdtar) to produce the ZIP archive instead. - let process = AsyncProcess( + // On FreeBSD, the unzip command is available in base but not the zip command. + // Therefore; we use libarchive(bsdtar) to produce the ZIP archive instead. + let process = AsyncProcess( arguments: [ self.tar, "-c", "--format", "zip", "-f", destinationPath.pathString, directory.basename, ], - workingDirectory: directory.parentDirectory - ) + workingDirectory: directory.parentDirectory + ) #else - // This is to work around `swift package-registry publish` tool failing on - // Amazon Linux 2 due to it having an earlier Glibc version (rdar://116370323) - // and therefore posix_spawn_file_actions_addchdir_np is unavailable. - // Instead of passing `workingDirectory` param to TSC.Process, which will trigger - // SPM_posix_spawn_file_actions_addchdir_np_supported check, we shell out and - // do `cd` explicitly before `zip`. - let process = AsyncProcess( - arguments: [ - "/bin/sh", - "-c", - "cd \(directory.parentDirectory.underlying.pathString) && \(self.zip) -ry \(destinationPath.pathString) \(directory.basename)" - ] - ) + // This is to work around `swift package-registry publish` tool failing on + // Amazon Linux 2 due to it having an earlier Glibc version (rdar://116370323) + // and therefore posix_spawn_file_actions_addchdir_np is unavailable. + // Instead of passing `workingDirectory` param to TSC.Process, which will trigger + // SPM_posix_spawn_file_actions_addchdir_np_supported check, we shell out and + // do `cd` explicitly before `zip`. + let process = AsyncProcess( + arguments: [ + "/bin/sh", + "-c", + "cd \(directory.parentDirectory.underlying.pathString) && \(self.zip) -ry \(destinationPath.pathString) \(directory.basename)", + ] + ) #endif guard let registrationKey = self.cancellator.register(process) else { @@ -164,7 +166,7 @@ public struct ZipArchiver: Archiver, Cancellable { } #if os(Windows) - let process = AsyncProcess(arguments: [windowsTar, "tf", path.pathString]) + let process = AsyncProcess(arguments: [windowsTar, "tf", path.pathString]) #else let process = AsyncProcess(arguments: [self.unzip, "-t", path.pathString]) #endif @@ -174,11 +176,13 @@ public struct ZipArchiver: Archiver, Cancellable { DispatchQueue.sharedConcurrent.async { defer { self.cancellator.deregister(registrationKey) } - completion(.init(catching: { - try process.launch() - let processResult = try process.waitUntilExit() - return processResult.exitStatus == .terminated(code: 0) - })) + completion( + .init(catching: { + try process.launch() + let processResult = try process.waitUntilExit() + return processResult.exitStatus == .terminated(code: 0) + }) + ) } } catch { return completion(.failure(error)) diff --git a/Sources/Basics/AuthorizationProvider.swift b/Sources/Basics/AuthorizationProvider.swift index 85e7b1a7c51..71719610102 100644 --- a/Sources/Basics/AuthorizationProvider.swift +++ b/Sources/Basics/AuthorizationProvider.swift @@ -15,7 +15,7 @@ import struct Foundation.Data import struct Foundation.Date import struct Foundation.URL #if canImport(Security) -import Security + import Security #endif public protocol AuthorizationProvider: Sendable { @@ -84,8 +84,9 @@ public final class NetrcAuthorizationProvider: AuthorizationProvider, Authorizat // Same entry already exists, no need to add or update let netrc = try? Self.load(fileSystem: self.fileSystem, path: self.path) - guard netrc?.machines - .first(where: { $0.name.lowercased() == machine && $0.login == user && $0.password == password }) == nil + guard + netrc?.machines + .first(where: { $0.name.lowercased() == machine && $0.login == user && $0.password == password }) == nil else { return } @@ -105,13 +106,15 @@ public final class NetrcAuthorizationProvider: AuthorizationProvider, Authorizat } } } catch { - throw AuthorizationProviderError + throw + AuthorizationProviderError .other("Failed to update netrc file at \(self.path): \(error.interpolationDescription)") } } public func remove(for url: URL) async throws { - throw AuthorizationProviderError + throw + AuthorizationProviderError .other("User must edit netrc file at \(self.path) manually to remove entries") } @@ -126,7 +129,7 @@ public final class NetrcAuthorizationProvider: AuthorizationProvider, Authorizat // Since updates are appended to the end of the file, we // take the _last_ match to use the most recent entry. if let machine = Self.machine(for: url), - let existing = self.machines.last(where: { $0.name.lowercased() == machine }) + let existing = self.machines.last(where: { $0.name.lowercased() == machine }) { return existing } @@ -168,284 +171,303 @@ public final class NetrcAuthorizationProvider: AuthorizationProvider, Authorizat // MARK: - Keychain #if canImport(Security) -public final class KeychainAuthorizationProvider: AuthorizationProvider, AuthorizationWriter { - private let observabilityScope: ObservabilityScope - - private let cache = ThreadSafeKeyValueStore() + public final class KeychainAuthorizationProvider: AuthorizationProvider, AuthorizationWriter { + private let observabilityScope: ObservabilityScope - public init(observabilityScope: ObservabilityScope) { - self.observabilityScope = observabilityScope - } + private let cache = ThreadSafeKeyValueStore() - public func addOrUpdate( - for url: URL, - user: String, - password: String, - persist: Bool = true - ) async throws { - guard let protocolHostPort = ProtocolHostPort(from: url) else { - throw AuthorizationProviderError.invalidURLHost + public init(observabilityScope: ObservabilityScope) { + self.observabilityScope = observabilityScope } - self.observabilityScope - .emit(debug: "add/update credentials for '\(protocolHostPort)' [\(url.absoluteString)] in keychain") + public func addOrUpdate( + for url: URL, + user: String, + password: String, + persist: Bool = true + ) async throws { + guard let protocolHostPort = ProtocolHostPort(from: url) else { + throw AuthorizationProviderError.invalidURLHost + } - if !persist { - self.cache[protocolHostPort.description] = (user, password) - return - } + self.observabilityScope + .emit(debug: "add/update credentials for '\(protocolHostPort)' [\(url.absoluteString)] in keychain") - let passwordData = Data(password.utf8) + if !persist { + self.cache[protocolHostPort.description] = (user, password) + return + } - if !(try self.update(protocolHostPort: protocolHostPort, account: user, password: passwordData)) { - try self.create(protocolHostPort: protocolHostPort, account: user, password: passwordData) - } - } + let passwordData = Data(password.utf8) - public func remove(for url: URL) async throws { - guard let protocolHostPort = ProtocolHostPort(from: url) else { - throw AuthorizationProviderError.invalidURLHost + if !(try self.update(protocolHostPort: protocolHostPort, account: user, password: passwordData)) { + try self.create(protocolHostPort: protocolHostPort, account: user, password: passwordData) + } } - self.observabilityScope - .emit(debug: "remove credentials for '\(protocolHostPort)' [\(url.absoluteString)] from keychain") - - try self.delete(protocolHostPort: protocolHostPort) - } + public func remove(for url: URL) async throws { + guard let protocolHostPort = ProtocolHostPort(from: url) else { + throw AuthorizationProviderError.invalidURLHost + } - public func authentication(for url: URL) -> (user: String, password: String)? { - guard let protocolHostPort = ProtocolHostPort(from: url) else { - return nil - } + self.observabilityScope + .emit(debug: "remove credentials for '\(protocolHostPort)' [\(url.absoluteString)] from keychain") - if let cached = self.cache[protocolHostPort.description] { - return cached + try self.delete(protocolHostPort: protocolHostPort) } - self.observabilityScope - .emit(debug: "search credentials for '\(protocolHostPort)' [\(url.absoluteString)] in keychain") - - do { - guard let existingItems = try self.search(protocolHostPort: protocolHostPort) as? [[String: Any]] else { - throw AuthorizationProviderError - .other("Failed to extract credentials for '\(protocolHostPort)' from keychain") + public func authentication(for url: URL) -> (user: String, password: String)? { + guard let protocolHostPort = ProtocolHostPort(from: url) else { + return nil } - // Log warning if there is more than one result - if existingItems.count > 1 { - self.observabilityScope - .emit( - warning: "multiple (\(existingItems.count)) keychain entries found for '\(protocolHostPort)' [\(url.absoluteString)]" - ) + if let cached = self.cache[protocolHostPort.description] { + return cached } - // Sort by modification timestamp - let sortedItems = existingItems.sorted { - switch ( - $0[kSecAttrModificationDate as String] as? Date, - $1[kSecAttrModificationDate as String] as? Date - ) { - case (nil, nil): - return false - case (_, nil): - return true - case (nil, _): - return false - case (.some(let left), .some(let right)): - return left < right + self.observabilityScope + .emit(debug: "search credentials for '\(protocolHostPort)' [\(url.absoluteString)] in keychain") + + do { + guard let existingItems = try self.search(protocolHostPort: protocolHostPort) as? [[String: Any]] else { + throw + AuthorizationProviderError + .other("Failed to extract credentials for '\(protocolHostPort)' from keychain") } - } - // Return most recently modified item - guard let mostRecent = sortedItems.last, - let created = mostRecent[kSecAttrCreationDate as String] as? Date, - // Get password for this specific item - let existingItem = try self.get( - protocolHostPort: protocolHostPort, - created: created, - modified: mostRecent[kSecAttrModificationDate as String] as? Date - ) as? [String: Any], - let passwordData = existingItem[kSecValueData as String] as? Data, - let account = existingItem[kSecAttrAccount as String] as? String - else { - throw AuthorizationProviderError - .other("Failed to extract credentials for '\(protocolHostPort)' from keychain") - } - - let password = String(decoding: passwordData, as: UTF8.self) + // Log warning if there is more than one result + if existingItems.count > 1 { + self.observabilityScope + .emit( + warning: "multiple (\(existingItems.count)) keychain entries found for '\(protocolHostPort)' [\(url.absoluteString)]" + ) + } - return (user: account, password: password) - } catch { - switch error { - case AuthorizationProviderError.notFound: - self.observabilityScope.emit(debug: "no credentials found for '\(protocolHostPort)' in keychain") - case AuthorizationProviderError.other(let detail): - self.observabilityScope.emit(error: detail) - default: - self.observabilityScope.emit( - error: "failed to find credentials for '\(protocolHostPort)' in keychain", - underlyingError: error - ) - } - return nil - } - } + // Sort by modification timestamp + let sortedItems = existingItems.sorted { + switch ( + $0[kSecAttrModificationDate as String] as? Date, + $1[kSecAttrModificationDate as String] as? Date + ) { + case (nil, nil): + return false + case (_, nil): + return true + case (nil, _): + return false + case (.some(let left), .some(let right)): + return left < right + } + } - private func create(protocolHostPort: ProtocolHostPort, account: String, password: Data) throws { - var query: [String: Any] = [kSecClass as String: kSecClassInternetPassword, - kSecAttrProtocol as String: protocolHostPort.protocolCFString, - kSecAttrServer as String: protocolHostPort.server, - kSecAttrAccount as String: account, - kSecValueData as String: password] + // Return most recently modified item + guard let mostRecent = sortedItems.last, + let created = mostRecent[kSecAttrCreationDate as String] as? Date, + // Get password for this specific item + let existingItem = try self.get( + protocolHostPort: protocolHostPort, + created: created, + modified: mostRecent[kSecAttrModificationDate as String] as? Date + ) as? [String: Any], + let passwordData = existingItem[kSecValueData as String] as? Data, + let account = existingItem[kSecAttrAccount as String] as? String + else { + throw + AuthorizationProviderError + .other("Failed to extract credentials for '\(protocolHostPort)' from keychain") + } - if let port = protocolHostPort.port { - query[kSecAttrPort as String] = port - } + let password = String(decoding: passwordData, as: UTF8.self) - let status = SecItemAdd(query as CFDictionary, nil) - guard status == errSecSuccess else { - throw AuthorizationProviderError - .other("Failed to save credentials for '\(protocolHostPort)' to keychain: status \(status)") + return (user: account, password: password) + } catch { + switch error { + case AuthorizationProviderError.notFound: + self.observabilityScope.emit(debug: "no credentials found for '\(protocolHostPort)' in keychain") + case AuthorizationProviderError.other(let detail): + self.observabilityScope.emit(error: detail) + default: + self.observabilityScope.emit( + error: "failed to find credentials for '\(protocolHostPort)' in keychain", + underlyingError: error + ) + } + return nil + } } - } - private func update(protocolHostPort: ProtocolHostPort, account: String, password: Data) throws -> Bool { - var query: [String: Any] = [kSecClass as String: kSecClassInternetPassword, - kSecAttrProtocol as String: protocolHostPort.protocolCFString, - kSecAttrServer as String: protocolHostPort.server] + private func create(protocolHostPort: ProtocolHostPort, account: String, password: Data) throws { + var query: [String: Any] = [ + kSecClass as String: kSecClassInternetPassword, + kSecAttrProtocol as String: protocolHostPort.protocolCFString, + kSecAttrServer as String: protocolHostPort.server, + kSecAttrAccount as String: account, + kSecValueData as String: password, + ] - if let port = protocolHostPort.port { - query[kSecAttrPort as String] = port + if let port = protocolHostPort.port { + query[kSecAttrPort as String] = port + } + + let status = SecItemAdd(query as CFDictionary, nil) + guard status == errSecSuccess else { + throw + AuthorizationProviderError + .other("Failed to save credentials for '\(protocolHostPort)' to keychain: status \(status)") + } } - let attributes: [String: Any] = [kSecAttrAccount as String: account, - kSecValueData as String: password] + private func update(protocolHostPort: ProtocolHostPort, account: String, password: Data) throws -> Bool { + var query: [String: Any] = [ + kSecClass as String: kSecClassInternetPassword, + kSecAttrProtocol as String: protocolHostPort.protocolCFString, + kSecAttrServer as String: protocolHostPort.server, + ] - let status = SecItemUpdate(query as CFDictionary, attributes as CFDictionary) - guard status != errSecItemNotFound else { - return false - } - guard status == errSecSuccess else { - throw AuthorizationProviderError - .other("Failed to update credentials for '\(protocolHostPort)' in keychain: status \(status)") - } - return true - } + if let port = protocolHostPort.port { + query[kSecAttrPort as String] = port + } - private func delete(protocolHostPort: ProtocolHostPort) throws { - var query: [String: Any] = [kSecClass as String: kSecClassInternetPassword, - kSecAttrProtocol as String: protocolHostPort.protocolCFString, - kSecAttrServer as String: protocolHostPort.server] + let attributes: [String: Any] = [ + kSecAttrAccount as String: account, + kSecValueData as String: password, + ] - if let port = protocolHostPort.port { - query[kSecAttrPort as String] = port + let status = SecItemUpdate(query as CFDictionary, attributes as CFDictionary) + guard status != errSecItemNotFound else { + return false + } + guard status == errSecSuccess else { + throw + AuthorizationProviderError + .other("Failed to update credentials for '\(protocolHostPort)' in keychain: status \(status)") + } + return true } - let status = SecItemDelete(query as CFDictionary) - guard status == errSecSuccess else { - throw AuthorizationProviderError - .other("Failed to delete credentials for '\(protocolHostPort)' from keychain: status \(status)") - } - } + private func delete(protocolHostPort: ProtocolHostPort) throws { + var query: [String: Any] = [ + kSecClass as String: kSecClassInternetPassword, + kSecAttrProtocol as String: protocolHostPort.protocolCFString, + kSecAttrServer as String: protocolHostPort.server, + ] - private func search(protocolHostPort: ProtocolHostPort) throws -> CFTypeRef? { - var query: [String: Any] = [kSecClass as String: kSecClassInternetPassword, - kSecAttrProtocol as String: protocolHostPort.protocolCFString, - kSecAttrServer as String: protocolHostPort.server, - kSecMatchLimit as String: kSecMatchLimitAll, // returns all matches - kSecReturnAttributes as String: true] - // https://developer.apple.com/documentation/security/keychain_services/keychain_items/searching_for_keychain_items - // Can't combine `kSecMatchLimitAll` and `kSecReturnData` (which contains password) - - if let port = protocolHostPort.port { - query[kSecAttrPort as String] = port - } + if let port = protocolHostPort.port { + query[kSecAttrPort as String] = port + } - var items: CFTypeRef? - // Search keychain for server's username and password, if any. - let status = SecItemCopyMatching(query as CFDictionary, &items) - guard status != errSecItemNotFound else { - throw AuthorizationProviderError.notFound - } - guard status == errSecSuccess else { - throw AuthorizationProviderError - .other("Failed to find credentials for '\(protocolHostPort)' in keychain: status \(status)") + let status = SecItemDelete(query as CFDictionary) + guard status == errSecSuccess else { + throw + AuthorizationProviderError + .other("Failed to delete credentials for '\(protocolHostPort)' from keychain: status \(status)") + } } - return items - } + private func search(protocolHostPort: ProtocolHostPort) throws -> CFTypeRef? { + var query: [String: Any] = [ + kSecClass as String: kSecClassInternetPassword, + kSecAttrProtocol as String: protocolHostPort.protocolCFString, + kSecAttrServer as String: protocolHostPort.server, + kSecMatchLimit as String: kSecMatchLimitAll, // returns all matches + kSecReturnAttributes as String: true, + ] + // https://developer.apple.com/documentation/security/keychain_services/keychain_items/searching_for_keychain_items + // Can't combine `kSecMatchLimitAll` and `kSecReturnData` (which contains password) - private func get(protocolHostPort: ProtocolHostPort, created: Date, modified: Date?) throws -> CFTypeRef? { - self.observabilityScope - .emit(debug: "read credentials for '\(protocolHostPort)', created at \(created), in keychain") + if let port = protocolHostPort.port { + query[kSecAttrPort as String] = port + } - var query: [String: Any] = [kSecClass as String: kSecClassInternetPassword, - kSecAttrProtocol as String: protocolHostPort.protocolCFString, - kSecAttrServer as String: protocolHostPort.server, - kSecAttrCreationDate as String: created, - kSecMatchLimit as String: kSecMatchLimitOne, // limit to one match - kSecReturnAttributes as String: true, - kSecReturnData as String: true] // password + var items: CFTypeRef? + // Search keychain for server's username and password, if any. + let status = SecItemCopyMatching(query as CFDictionary, &items) + guard status != errSecItemNotFound else { + throw AuthorizationProviderError.notFound + } + guard status == errSecSuccess else { + throw + AuthorizationProviderError + .other("Failed to find credentials for '\(protocolHostPort)' in keychain: status \(status)") + } - if let port = protocolHostPort.port { - query[kSecAttrPort as String] = port - } - if let modified { - query[kSecAttrModificationDate as String] = modified + return items } - var item: CFTypeRef? - // Search keychain for server's username and password, if any. - let status = SecItemCopyMatching(query as CFDictionary, &item) - guard status != errSecItemNotFound else { - throw AuthorizationProviderError.notFound - } - guard status == errSecSuccess else { - throw AuthorizationProviderError - .other("Failed to find credentials for '\(protocolHostPort)' in keychain: status \(status)") - } + private func get(protocolHostPort: ProtocolHostPort, created: Date, modified: Date?) throws -> CFTypeRef? { + self.observabilityScope + .emit(debug: "read credentials for '\(protocolHostPort)', created at \(created), in keychain") - return item - } + var query: [String: Any] = [ + kSecClass as String: kSecClassInternetPassword, + kSecAttrProtocol as String: protocolHostPort.protocolCFString, + kSecAttrServer as String: protocolHostPort.server, + kSecAttrCreationDate as String: created, + kSecMatchLimit as String: kSecMatchLimitOne, // limit to one match + kSecReturnAttributes as String: true, + kSecReturnData as String: true, + ] // password - struct ProtocolHostPort: Hashable, CustomStringConvertible { - let `protocol`: String? - let host: String - let port: Int? + if let port = protocolHostPort.port { + query[kSecAttrPort as String] = port + } + if let modified { + query[kSecAttrModificationDate as String] = modified + } + + var item: CFTypeRef? + // Search keychain for server's username and password, if any. + let status = SecItemCopyMatching(query as CFDictionary, &item) + guard status != errSecItemNotFound else { + throw AuthorizationProviderError.notFound + } + guard status == errSecSuccess else { + throw + AuthorizationProviderError + .other("Failed to find credentials for '\(protocolHostPort)' in keychain: status \(status)") + } - var server: String { - self.host + return item } - var protocolCFString: CFString { - // See - // https://developer.apple.com/documentation/security/keychain_services/keychain_items/item_attribute_keys_and_values?language=swift - // for a list of possible values for the `kSecAttrProtocol` attribute. - switch self.protocol { - case "https": - return kSecAttrProtocolHTTPS - case "http": - return kSecAttrProtocolHTTP - default: - return kSecAttrProtocolHTTPS + struct ProtocolHostPort: Hashable, CustomStringConvertible { + let `protocol`: String? + let host: String + let port: Int? + + var server: String { + self.host } - } - init?(from url: URL) { - guard let host = url.host?.lowercased(), !host.isEmpty else { - return nil + var protocolCFString: CFString { + // See + // https://developer.apple.com/documentation/security/keychain_services/keychain_items/item_attribute_keys_and_values?language=swift + // for a list of possible values for the `kSecAttrProtocol` attribute. + switch self.protocol { + case "https": + return kSecAttrProtocolHTTPS + case "http": + return kSecAttrProtocolHTTP + default: + return kSecAttrProtocolHTTPS + } } - self.protocol = url.scheme?.lowercased() - self.host = host - self.port = url.port - } + init?(from url: URL) { + guard let host = url.host?.lowercased(), !host.isEmpty else { + return nil + } + + self.protocol = url.scheme?.lowercased() + self.host = host + self.port = url.port + } - var description: String { - "\(self.protocol.map { "\($0)://" } ?? "")\(self.host)\(self.port.map { ":\($0)" } ?? "")" + var description: String { + "\(self.protocol.map { "\($0)://" } ?? "")\(self.host)\(self.port.map { ":\($0)" } ?? "")" + } } } -} #endif // MARK: - Composite @@ -471,8 +493,8 @@ public struct CompositeAuthorizationProvider: AuthorizationProvider { case let provider as NetrcAuthorizationProvider: self.observabilityScope.emit(info: "credentials for \(url) found in netrc file at \(provider.path)") #if canImport(Security) - case is KeychainAuthorizationProvider: - self.observabilityScope.emit(info: "credentials for \(url) found in keychain") + case is KeychainAuthorizationProvider: + self.observabilityScope.emit(info: "credentials for \(url) found in keychain") #endif default: self.observabilityScope.emit(info: "credentials for \(url) found in \(provider)") diff --git a/Sources/Basics/Cancellator.swift b/Sources/Basics/Cancellator.swift index 9cb30617d57..7fb4ee65263 100644 --- a/Sources/Basics/Cancellator.swift +++ b/Sources/Basics/Cancellator.swift @@ -14,9 +14,9 @@ import Dispatch import Foundation import class TSCBasic.Thread #if canImport(WinSDK) -import WinSDK + import WinSDK #elseif canImport(Android) -import Android + import Android #endif public typealias CancellationHandler = @Sendable (DispatchTime) async throws -> Void @@ -36,8 +36,8 @@ public final class Cancellator: Cancellable, Sendable { } #if os(Windows) - // unfortunately this is needed for C callback handlers used by Windows shutdown handler - static var shared: Cancellator? + // unfortunately this is needed for C callback handlers used by Windows shutdown handler + static var shared: Cancellator? #endif /// Installs signal handlers to terminate sub-processes on cancellation. @@ -46,51 +46,54 @@ public final class Cancellator: Cancellable, Sendable { precondition(!Self.isSignalHandlerInstalled) #if os(Windows) - // Closures passed to `SetConsoleCtrlHandler` can't capture context, working around that with a global. - Self.shared = self + // Closures passed to `SetConsoleCtrlHandler` can't capture context, working around that with a global. + Self.shared = self - // set shutdown handler to terminate sub-processes, etc - _ = SetConsoleCtrlHandler({ _ in - // Terminate all processes on receiving an interrupt signal. - try? Cancellator.shared?.cancel(deadline: .now() + .seconds(30)) + // set shutdown handler to terminate sub-processes, etc + _ = SetConsoleCtrlHandler( + { _ in + // Terminate all processes on receiving an interrupt signal. + try? Cancellator.shared?.cancel(deadline: .now() + .seconds(30)) - // Reset the handler. - _ = SetConsoleCtrlHandler(nil, false) + // Reset the handler. + _ = SetConsoleCtrlHandler(nil, false) - // Exit as if by signal() - TerminateProcess(GetCurrentProcess(), 3) + // Exit as if by signal() + TerminateProcess(GetCurrentProcess(), 3) - return true - }, true) - #else - // trap SIGINT to terminate sub-processes, etc - signal(SIGINT, SIG_IGN) - let interruptSignalSource = DispatchSource.makeSignalSource(signal: SIGINT) - interruptSignalSource.setEventHandler { [weak self] in - // cancel the trap? - interruptSignalSource.cancel() - - // Terminate all processes on receiving an interrupt signal. - try? self?.cancel(deadline: .now() + .seconds(30)) - - // Install the default signal handler. - var action = sigaction() - #if canImport(Darwin) || os(OpenBSD) || os(FreeBSD) - action.__sigaction_u.__sa_handler = SIG_DFL - #elseif canImport(Musl) - action.__sa_handler.sa_handler = SIG_DFL - #elseif os(Android) - action.sa_handler = SIG_DFL - #else - action.__sigaction_handler = unsafeBitCast( - SIG_DFL, - to: sigaction.__Unnamed_union___sigaction_handler.self + return true + }, + true ) - #endif - sigaction(SIGINT, &action, nil) - kill(getpid(), SIGINT) - } - interruptSignalSource.resume() + #else + // trap SIGINT to terminate sub-processes, etc + signal(SIGINT, SIG_IGN) + let interruptSignalSource = DispatchSource.makeSignalSource(signal: SIGINT) + interruptSignalSource.setEventHandler { [weak self] in + // cancel the trap? + interruptSignalSource.cancel() + + // Terminate all processes on receiving an interrupt signal. + try? self?.cancel(deadline: .now() + .seconds(30)) + + // Install the default signal handler. + var action = sigaction() + #if canImport(Darwin) || os(OpenBSD) || os(FreeBSD) + action.__sigaction_u.__sa_handler = SIG_DFL + #elseif canImport(Musl) + action.__sa_handler.sa_handler = SIG_DFL + #elseif os(Android) + action.sa_handler = SIG_DFL + #else + action.__sigaction_handler = unsafeBitCast( + SIG_DFL, + to: sigaction.__Unnamed_union___sigaction_handler.self + ) + #endif + sigaction(SIGINT, &action, nil) + kill(getpid(), SIGINT) + } + interruptSignalSource.resume() #endif Self.isSignalHandlerInstalled = true @@ -129,9 +132,9 @@ public final class Cancellator: Cancellable, Sendable { } #if !canImport(Darwin) || os(macOS) - public func register(_ process: Foundation.Process) -> RegistrationKey? { - self.register(name: "\(process.description)", handler: process.terminate(timeout:)) - } + public func register(_ process: Foundation.Process) -> RegistrationKey? { + self.register(name: "\(process.description)", handler: process.terminate(timeout:)) + } #endif public func deregister(_ key: RegistrationKey) { @@ -212,10 +215,10 @@ public struct CancellationError: Error, CustomStringConvertible { static func failedToRegisterProcess(_ process: AsyncProcess) -> Self { Self( description: """ - failed to register a cancellation handler for this process invocation `\( - process.arguments.joined(separator: " ") - )` - """ + failed to register a cancellation handler for this process invocation `\( + process.arguments.joined(separator: " ") + )` + """ ) } } @@ -231,47 +234,47 @@ extension AsyncProcess { if case .timedOut = forceKillSemaphore.wait(timeout: timeout) { // send a force-kill signal #if os(Windows) - self.signal(SIGTERM) + self.signal(SIGTERM) #else - self.signal(SIGKILL) + self.signal(SIGKILL) #endif } } forceKillThread.start() _ = try? self.waitUntilExit() - forceKillSemaphore.signal() // let the force-kill thread know we do not need it any more + forceKillSemaphore.signal() // let the force-kill thread know we do not need it any more // join the force-kill thread thread so we don't exit before everything terminates forceKillThread.join() } } #if !canImport(Darwin) || os(macOS) -extension Foundation.Process { - fileprivate func terminate(timeout: DispatchTime) { - guard self.isRunning else { - return - } + extension Foundation.Process { + fileprivate func terminate(timeout: DispatchTime) { + guard self.isRunning else { + return + } - // send graceful shutdown signal (SIGINT) - self.interrupt() + // send graceful shutdown signal (SIGINT) + self.interrupt() - // start a thread to see if we need to terminate more forcibly - let forceKillSemaphore = DispatchSemaphore(value: 0) - let forceKillThread = TSCBasic.Thread { - if case .timedOut = forceKillSemaphore.wait(timeout: timeout) { - guard self.isRunning else { - return - } + // start a thread to see if we need to terminate more forcibly + let forceKillSemaphore = DispatchSemaphore(value: 0) + let forceKillThread = TSCBasic.Thread { + if case .timedOut = forceKillSemaphore.wait(timeout: timeout) { + guard self.isRunning else { + return + } - // force kill (SIGTERM) - self.terminate() + // force kill (SIGTERM) + self.terminate() + } } + forceKillThread.start() + self.waitUntilExit() + forceKillSemaphore.signal() // let the force-kill thread know we do not need it any more + // join the force-kill thread thread so we don't exit before everything terminates + forceKillThread.join() } - forceKillThread.start() - self.waitUntilExit() - forceKillSemaphore.signal() // let the force-kill thread know we do not need it any more - // join the force-kill thread thread so we don't exit before everything terminates - forceKillThread.join() } -} #endif diff --git a/Sources/Basics/Concurrency/AsyncProcess.swift b/Sources/Basics/Concurrency/AsyncProcess.swift index 17149e833bc..5b31cdb2211 100644 --- a/Sources/Basics/Concurrency/AsyncProcess.swift +++ b/Sources/Basics/Concurrency/AsyncProcess.swift @@ -13,22 +13,20 @@ import Dispatch import Foundation #if os(Windows) -import TSCLibc + import TSCLibc #elseif canImport(Android) -import Android + import Android #endif #if !os(Windows) && !canImport(Darwin) -#if USE_IMPL_ONLY_IMPORTS -@_implementationOnly -import func TSCclibc.SPM_posix_spawn_file_actions_addchdir_np_supported - -@_implementationOnly -import func TSCclibc.SPM_posix_spawn_file_actions_addchdir_np -#else -private import func TSCclibc.SPM_posix_spawn_file_actions_addchdir_np_supported -private import func TSCclibc.SPM_posix_spawn_file_actions_addchdir_np -#endif // #if USE_IMPL_ONLY_IMPORTS + #if USE_IMPL_ONLY_IMPORTS + @_implementationOnly import func TSCclibc.SPM_posix_spawn_file_actions_addchdir_np_supported + + @_implementationOnly import func TSCclibc.SPM_posix_spawn_file_actions_addchdir_np + #else + private import func TSCclibc.SPM_posix_spawn_file_actions_addchdir_np_supported + private import func TSCclibc.SPM_posix_spawn_file_actions_addchdir_np + #endif // #if USE_IMPL_ONLY_IMPORTS #endif import class TSCBasic.CStringArray @@ -55,11 +53,11 @@ package struct AsyncProcessResult: CustomStringConvertible, Sendable { /// The process was terminated normally with a exit code. case terminated(code: Int32) #if os(Windows) - /// The process was terminated abnormally. - case abnormal(exception: UInt32) + /// The process was terminated abnormally. + case abnormal(exception: UInt32) #else - /// The process was terminated due to a signal. - case signalled(signal: Int32) + /// The process was terminated due to a signal. + case signalled(signal: Int32) #endif } @@ -93,18 +91,18 @@ package struct AsyncProcessResult: CustomStringConvertible, Sendable { ) { let exitStatus: ExitStatus #if os(Windows) - if normal { - exitStatus = .terminated(code: exitStatusCode) - } else { - exitStatus = .abnormal(exception: UInt32(exitStatusCode)) - } + if normal { + exitStatus = .terminated(code: exitStatusCode) + } else { + exitStatus = .abnormal(exception: UInt32(exitStatusCode)) + } #else - if WIFSIGNALED(exitStatusCode) { - exitStatus = .signalled(signal: WTERMSIG(exitStatusCode)) - } else { - precondition(WIFEXITED(exitStatusCode), "unexpected exit status \(exitStatusCode)") - exitStatus = .terminated(code: WEXITSTATUS(exitStatusCode)) - } + if WIFSIGNALED(exitStatusCode) { + exitStatus = .signalled(signal: WTERMSIG(exitStatusCode)) + } else { + precondition(WIFEXITED(exitStatusCode), "unexpected exit status \(exitStatusCode)") + exitStatus = .terminated(code: WEXITSTATUS(exitStatusCode)) + } #endif self.init( arguments: arguments, @@ -251,9 +249,9 @@ package final class AsyncProcess { /// Typealias for process id type. #if !os(Windows) - package typealias ProcessID = pid_t + package typealias ProcessID = pid_t #else - package typealias ProcessID = DWORD + package typealias ProcessID = DWORD #endif /// Typealias for stdout/stderr output closure. @@ -276,7 +274,8 @@ package final class AsyncProcess { Self.loggingHandlerLock.withLock { self._loggingHandler } - } set { + } + set { Self.loggingHandlerLock.withLock { self._loggingHandler = newValue } @@ -295,12 +294,12 @@ package final class AsyncProcess { /// The process id of the spawned process, available after the process is launched. #if os(Windows) - private var _process: Foundation.Process? - package var processID: ProcessID { - DWORD(self._process?.processIdentifier ?? 0) - } + private var _process: Foundation.Process? + package var processID: ProcessID { + DWORD(self._process?.processIdentifier ?? 0) + } #else - package private(set) var processID = ProcessID() + package private(set) var processID = ProcessID() #endif // process execution mutable state @@ -491,306 +490,306 @@ package final class AsyncProcess { } #if os(Windows) - let process = Foundation.Process() - self._process = process - process.arguments = Array(self.arguments.dropFirst()) // Avoid including the executable URL twice. - if let workingDirectory { - process.currentDirectoryURL = workingDirectory.asURL - } - process.executableURL = executablePath.asURL - process.environment = .init(self.environment) + let process = Foundation.Process() + self._process = process + process.arguments = Array(self.arguments.dropFirst()) // Avoid including the executable URL twice. + if let workingDirectory { + process.currentDirectoryURL = workingDirectory.asURL + } + process.executableURL = executablePath.asURL + process.environment = .init(self.environment) - let stdinPipe = Pipe() - process.standardInput = stdinPipe + let stdinPipe = Pipe() + process.standardInput = stdinPipe - let group = DispatchGroup() + let group = DispatchGroup() - var stdout: [UInt8] = [] - let stdoutLock = NSLock() + var stdout: [UInt8] = [] + let stdoutLock = NSLock() - var stderr: [UInt8] = [] - let stderrLock = NSLock() + var stderr: [UInt8] = [] + let stderrLock = NSLock() - if self.outputRedirection.redirectsOutput { - let stdoutPipe = Pipe() - let stderrPipe = Pipe() + if self.outputRedirection.redirectsOutput { + let stdoutPipe = Pipe() + let stderrPipe = Pipe() - group.enter() - stdoutPipe.fileHandleForReading.readabilityHandler = { (fh: FileHandle) in - let data = (try? fh.read(upToCount: Int.max)) ?? Data() - if data.count == 0 { - stdoutPipe.fileHandleForReading.readabilityHandler = nil - group.leave() - } else { - let contents = data.withUnsafeBytes { [UInt8]($0) } - self.outputRedirection.outputClosures?.stdoutClosure(contents) - stdoutLock.withLock { - stdout += contents + group.enter() + stdoutPipe.fileHandleForReading.readabilityHandler = { (fh: FileHandle) in + let data = (try? fh.read(upToCount: Int.max)) ?? Data() + if data.count == 0 { + stdoutPipe.fileHandleForReading.readabilityHandler = nil + group.leave() + } else { + let contents = data.withUnsafeBytes { [UInt8]($0) } + self.outputRedirection.outputClosures?.stdoutClosure(contents) + stdoutLock.withLock { + stdout += contents + } } } - } - group.enter() - stderrPipe.fileHandleForReading.readabilityHandler = { (fh: FileHandle) in - let data = (try? fh.read(upToCount: Int.max)) ?? Data() - if data.count == 0 { - stderrPipe.fileHandleForReading.readabilityHandler = nil - group.leave() - } else { - let contents = data.withUnsafeBytes { [UInt8]($0) } - self.outputRedirection.outputClosures?.stderrClosure(contents) - stderrLock.withLock { - stderr += contents + group.enter() + stderrPipe.fileHandleForReading.readabilityHandler = { (fh: FileHandle) in + let data = (try? fh.read(upToCount: Int.max)) ?? Data() + if data.count == 0 { + stderrPipe.fileHandleForReading.readabilityHandler = nil + group.leave() + } else { + let contents = data.withUnsafeBytes { [UInt8]($0) } + self.outputRedirection.outputClosures?.stderrClosure(contents) + stderrLock.withLock { + stderr += contents + } } } - } - - process.standardOutput = stdoutPipe - process.standardError = stderrPipe - } - // first set state then start reading threads - let sync = DispatchGroup() - sync.enter() - self.stateLock.withLock { - self.state = .readingOutput(sync: sync) - } + process.standardOutput = stdoutPipe + process.standardError = stderrPipe + } - group.notify(queue: self.completionQueue) { + // first set state then start reading threads + let sync = DispatchGroup() + sync.enter() self.stateLock.withLock { - self.state = .outputReady(stdout: .success(stdout), stderr: .success(stderr)) + self.state = .readingOutput(sync: sync) } - sync.leave() - } - try process.run() - return stdinPipe.fileHandleForWriting - #elseif(!canImport(Darwin) || os(macOS)) - // Initialize the spawn attributes. - #if os(Android) - var attributes: posix_spawnattr_t! = nil - #elseif canImport(Darwin) || os(OpenBSD) || os(FreeBSD) - var attributes: posix_spawnattr_t? = nil - #else - var attributes = posix_spawnattr_t() - #endif - posix_spawnattr_init(&attributes) - defer { posix_spawnattr_destroy(&attributes) } - - // Unmask all signals. - var noSignals = sigset_t() - sigemptyset(&noSignals) - posix_spawnattr_setsigmask(&attributes, &noSignals) - - // Reset all signals to default behavior. - #if canImport(Darwin) - var mostSignals = sigset_t() - sigfillset(&mostSignals) - sigdelset(&mostSignals, SIGKILL) - sigdelset(&mostSignals, SIGSTOP) - posix_spawnattr_setsigdefault(&attributes, &mostSignals) - #else - // On Linux, this can only be used to reset signals that are legal to - // modify, so we have to take care about the set we use. - var mostSignals = sigset_t() - sigemptyset(&mostSignals) - for i in 1 ..< SIGSYS { - if i == SIGKILL || i == SIGSTOP { - continue + group.notify(queue: self.completionQueue) { + self.stateLock.withLock { + self.state = .outputReady(stdout: .success(stdout), stderr: .success(stderr)) + } + sync.leave() } - sigaddset(&mostSignals, i) - } - posix_spawnattr_setsigdefault(&attributes, &mostSignals) - #endif - - // Set the attribute flags. - var flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF - if self.startNewProcessGroup { - // Establish a separate process group. - flags |= POSIX_SPAWN_SETPGROUP - posix_spawnattr_setpgroup(&attributes, 0) - } - posix_spawnattr_setflags(&attributes, Int16(flags)) + try process.run() + return stdinPipe.fileHandleForWriting + #elseif (!canImport(Darwin) || os(macOS)) + // Initialize the spawn attributes. + #if os(Android) + var attributes: posix_spawnattr_t! = nil + #elseif canImport(Darwin) || os(OpenBSD) || os(FreeBSD) + var attributes: posix_spawnattr_t? = nil + #else + var attributes = posix_spawnattr_t() + #endif + posix_spawnattr_init(&attributes) + defer { posix_spawnattr_destroy(&attributes) } - // Setup the file actions. - #if os(Android) - var fileActions: posix_spawn_file_actions_t! = nil - #elseif canImport(Darwin) || os(Android) || os(OpenBSD) || os(FreeBSD) - var fileActions: posix_spawn_file_actions_t? = nil - #else - var fileActions = posix_spawn_file_actions_t() - #endif - posix_spawn_file_actions_init(&fileActions) - defer { posix_spawn_file_actions_destroy(&fileActions) } + // Unmask all signals. + var noSignals = sigset_t() + sigemptyset(&noSignals) + posix_spawnattr_setsigmask(&attributes, &noSignals) - if let workingDirectory = workingDirectory?.pathString { + // Reset all signals to default behavior. #if canImport(Darwin) - posix_spawn_file_actions_addchdir_np(&fileActions, workingDirectory) + var mostSignals = sigset_t() + sigfillset(&mostSignals) + sigdelset(&mostSignals, SIGKILL) + sigdelset(&mostSignals, SIGSTOP) + posix_spawnattr_setsigdefault(&attributes, &mostSignals) #else - guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { - throw AsyncProcess.Error.workingDirectoryNotSupported - } - - SPM_posix_spawn_file_actions_addchdir_np(&fileActions, workingDirectory) + // On Linux, this can only be used to reset signals that are legal to + // modify, so we have to take care about the set we use. + var mostSignals = sigset_t() + sigemptyset(&mostSignals) + for i in 1..? - let pendingLock = NSLock() + posix_spawn_file_actions_adddup2(&fileActions, 1, 1) + posix_spawn_file_actions_adddup2(&fileActions, 2, 2) + } - let outputClosures = self.outputRedirection.outputClosures + var resolvedArgs = self.arguments + if workingDirectory != nil { + resolvedArgs[0] = executablePath.pathString + } + let argv = CStringArray(resolvedArgs) + let env = CStringArray(environment.map { "\($0.0)=\($0.1)" }) + let rv = posix_spawnp(&self.processID, argv.cArray[0]!, &fileActions, &attributes, argv.cArray, env.cArray) - // Close the local write end of the output pipe. - try close(fd: outputPipe[1]) + guard rv == 0 else { + throw SystemError.posix_spawn(rv, self.arguments) + } - // Create a thread and start reading the output on it. - group.enter() - let stdoutThread = Thread { [weak self] in - if let readResult = self?.readOutput( - onFD: outputPipe[0], - outputClosure: outputClosures?.stdoutClosure - ) { - pendingLock.withLock { - if let stderrResult = pending { - self?.stateLock.withLock { - self?.state = .outputReady(stdout: readResult, stderr: stderrResult) - } - } else { - pending = readResult - } - } - group.leave() - } else if let stderrResult = (pendingLock.withLock { pending }) { - // TODO: this is more of an error - self?.stateLock.withLock { - self?.state = .outputReady(stdout: .success([]), stderr: stderrResult) - } - group.leave() + do { + // Close the local read end of the input pipe. + try close(fd: stdinPipe[0]) + + let group = DispatchGroup() + if !self.outputRedirection.redirectsOutput { + // no stdout or stderr in this case + self.stateLock.withLock { + self.state = .outputReady(stdout: .success([]), stderr: .success([])) } - } + } else { + var pending: Result<[UInt8], Swift.Error>? + let pendingLock = NSLock() + + let outputClosures = self.outputRedirection.outputClosures - // Only schedule a thread for stderr if no redirect was requested. - var stderrThread: Thread? = nil - if !self.outputRedirection.redirectStderr { - // Close the local write end of the stderr pipe. - try close(fd: stderrPipe[1]) + // Close the local write end of the output pipe. + try close(fd: outputPipe[1]) - // Create a thread and start reading the stderr output on it. + // Create a thread and start reading the output on it. group.enter() - stderrThread = Thread { [weak self] in + let stdoutThread = Thread { [weak self] in if let readResult = self?.readOutput( - onFD: stderrPipe[0], - outputClosure: outputClosures?.stderrClosure + onFD: outputPipe[0], + outputClosure: outputClosures?.stdoutClosure ) { pendingLock.withLock { - if let stdoutResult = pending { + if let stderrResult = pending { self?.stateLock.withLock { - self?.state = .outputReady(stdout: stdoutResult, stderr: readResult) + self?.state = .outputReady(stdout: readResult, stderr: stderrResult) } } else { pending = readResult } } group.leave() - } else if let stdoutResult = (pendingLock.withLock { pending }) { + } else if let stderrResult = (pendingLock.withLock { pending }) { // TODO: this is more of an error self?.stateLock.withLock { - self?.state = .outputReady(stdout: stdoutResult, stderr: .success([])) + self?.state = .outputReady(stdout: .success([]), stderr: stderrResult) } group.leave() } } - } else { - pendingLock.withLock { - pending = .success([]) // no stderr in this case + + // Only schedule a thread for stderr if no redirect was requested. + var stderrThread: Thread? = nil + if !self.outputRedirection.redirectStderr { + // Close the local write end of the stderr pipe. + try close(fd: stderrPipe[1]) + + // Create a thread and start reading the stderr output on it. + group.enter() + stderrThread = Thread { [weak self] in + if let readResult = self?.readOutput( + onFD: stderrPipe[0], + outputClosure: outputClosures?.stderrClosure + ) { + pendingLock.withLock { + if let stdoutResult = pending { + self?.stateLock.withLock { + self?.state = .outputReady(stdout: stdoutResult, stderr: readResult) + } + } else { + pending = readResult + } + } + group.leave() + } else if let stdoutResult = (pendingLock.withLock { pending }) { + // TODO: this is more of an error + self?.stateLock.withLock { + self?.state = .outputReady(stdout: stdoutResult, stderr: .success([])) + } + group.leave() + } + } + } else { + pendingLock.withLock { + pending = .success([]) // no stderr in this case + } } - } - // first set state then start reading threads - self.stateLock.withLock { - self.state = .readingOutput(sync: group) + // first set state then start reading threads + self.stateLock.withLock { + self.state = .readingOutput(sync: group) + } + + stdoutThread.start() + stderrThread?.start() } - stdoutThread.start() - stderrThread?.start() + return stdinStream + } catch { + throw AsyncProcessResult.Error.systemError(arguments: self.arguments, underlyingError: error) } - - return stdinStream - } catch { - throw AsyncProcessResult.Error.systemError(arguments: self.arguments, underlyingError: error) - } #else - preconditionFailure("Process spawning is not available") - #endif // POSIX implementation + preconditionFailure("Process spawning is not available") + #endif // POSIX implementation } /// Executes the process I/O state machine, returning the result when finished. @@ -843,21 +842,21 @@ package final class AsyncProcess { defer { self.stateLock.unlock() } // Wait until process finishes execution. #if os(Windows) - precondition(self._process != nil, "The process is not yet launched.") - let p = self._process! - p.waitUntilExit() - let exitStatusCode = p.terminationStatus - let normalExit = p.terminationReason == .exit + precondition(self._process != nil, "The process is not yet launched.") + let p = self._process! + p.waitUntilExit() + let exitStatusCode = p.terminationStatus + let normalExit = p.terminationReason == .exit #else - var exitStatusCode: Int32 = 0 - var result = waitpid(processID, &exitStatusCode, 0) - while result == -1 && errno == EINTR { - result = waitpid(self.processID, &exitStatusCode, 0) - } - if result == -1 { - self.state = .failed(SystemError.waitpid(errno)) - } - let normalExit = !WIFSIGNALED(result) + var exitStatusCode: Int32 = 0 + var result = waitpid(processID, &exitStatusCode, 0) + while result == -1 && errno == EINTR { + result = waitpid(self.processID, &exitStatusCode, 0) + } + if result == -1 { + self.state = .failed(SystemError.waitpid(errno)) + } + let normalExit = !WIFSIGNALED(result) #endif // Construct the result. @@ -877,48 +876,48 @@ package final class AsyncProcess { } #if !os(Windows) - /// Reads the given fd and returns its result. - /// - /// Closes the fd before returning. - private func readOutput(onFD fd: Int32, outputClosure: OutputClosure?) -> Result<[UInt8], Swift.Error> { - // Read all of the data from the output pipe. - let N = 4096 - var buf = [UInt8](repeating: 0, count: N + 1) - - var out = [UInt8]() - var error: Swift.Error? = nil - loop: while true { - let n = read(fd, &buf, N) - switch n { - case -1: - if errno == EINTR { - continue - } else { - error = SystemError.read(errno) + /// Reads the given fd and returns its result. + /// + /// Closes the fd before returning. + private func readOutput(onFD fd: Int32, outputClosure: OutputClosure?) -> Result<[UInt8], Swift.Error> { + // Read all of the data from the output pipe. + let N = 4096 + var buf = [UInt8](repeating: 0, count: N + 1) + + var out = [UInt8]() + var error: Swift.Error? = nil + loop: while true { + let n = read(fd, &buf, N) + switch n { + case -1: + if errno == EINTR { + continue + } else { + error = SystemError.read(errno) + break loop + } + case 0: + // Close the read end of the output pipe. + // We should avoid closing the read end of the pipe in case + // -1 because the child process may still have content to be + // flushed into the write end of the pipe. If the read end of the + // pipe is closed, then a write will cause a SIGPIPE signal to + // be generated for the calling process. If the calling process is + // ignoring this signal, then write fails with the error EPIPE. + close(fd) break loop - } - case 0: - // Close the read end of the output pipe. - // We should avoid closing the read end of the pipe in case - // -1 because the child process may still have content to be - // flushed into the write end of the pipe. If the read end of the - // pipe is closed, then a write will cause a SIGPIPE signal to - // be generated for the calling process. If the calling process is - // ignoring this signal, then write fails with the error EPIPE. - close(fd) - break loop - default: - let data = buf[0 ..< n] - if let outputClosure { - outputClosure(Array(data)) - } else { - out += data + default: + let data = buf[0.. Bool { - _WSTATUS(status) == 0 -} + #if canImport(Darwin) + private typealias swiftpm_posix_spawn_file_actions_t = posix_spawn_file_actions_t? + #else + private typealias swiftpm_posix_spawn_file_actions_t = posix_spawn_file_actions_t + #endif -private func _WSTATUS(_ status: Int32) -> Int32 { - status & 0x7F -} + private func WIFEXITED(_ status: Int32) -> Bool { + _WSTATUS(status) == 0 + } -private func WIFSIGNALED(_ status: Int32) -> Bool { - (_WSTATUS(status) != 0) && (_WSTATUS(status) != 0x7F) -} + private func _WSTATUS(_ status: Int32) -> Int32 { + status & 0x7F + } -private func WEXITSTATUS(_ status: Int32) -> Int32 { - (status >> 8) & 0xFF -} + private func WIFSIGNALED(_ status: Int32) -> Bool { + (_WSTATUS(status) != 0) && (_WSTATUS(status) != 0x7F) + } -private func WTERMSIG(_ status: Int32) -> Int32 { - status & 0x7F -} + private func WEXITSTATUS(_ status: Int32) -> Int32 { + (status >> 8) & 0xFF + } -/// Open the given pipe. -private func open(pipe buffer: inout [Int32]) throws { - let rv = pipe(&buffer) - guard rv == 0 else { - throw SystemError.pipe(rv) + private func WTERMSIG(_ status: Int32) -> Int32 { + status & 0x7F } -} -/// Close the given fd. -private func close(fd: Int32) throws { - func innerClose(_ fd: inout Int32) throws { - let rv = close(fd) + /// Open the given pipe. + private func open(pipe buffer: inout [Int32]) throws { + let rv = pipe(&buffer) guard rv == 0 else { - throw SystemError.close(rv) + throw SystemError.pipe(rv) } } - var innerFd = fd - try innerClose(&innerFd) -} -extension AsyncProcess.Error: CustomStringConvertible { - package var description: String { - switch self { - case .missingExecutableProgram(let program): - "could not find executable for '\(program)'" - case .workingDirectoryNotSupported: - "workingDirectory is not supported in this platform" - case .stdinUnavailable: - "could not open stdin on this platform" + /// Close the given fd. + private func close(fd: Int32) throws { + func innerClose(_ fd: inout Int32) throws { + let rv = close(fd) + guard rv == 0 else { + throw SystemError.close(rv) + } } + var innerFd = fd + try innerClose(&innerFd) } -} -extension AsyncProcess.Error: CustomNSError { - package var errorUserInfo: [String: Any] { - [NSLocalizedDescriptionKey: self.description] + extension AsyncProcess.Error: CustomStringConvertible { + package var description: String { + switch self { + case .missingExecutableProgram(let program): + "could not find executable for '\(program)'" + case .workingDirectoryNotSupported: + "workingDirectory is not supported in this platform" + case .stdinUnavailable: + "could not open stdin on this platform" + } + } + } + + extension AsyncProcess.Error: CustomNSError { + package var errorUserInfo: [String: Any] { + [NSLocalizedDescriptionKey: self.description] + } } -} #endif @@ -1305,11 +1304,11 @@ extension AsyncProcessResult.Error: CustomStringConvertible { case .terminated(let code): str.append(contentsOf: "terminated(\(code)): ") #if os(Windows) - case .abnormal(let exception): - str.append(contentsOf: "abnormal(\(exception)): ") + case .abnormal(let exception): + str.append(contentsOf: "abnormal(\(exception)): ") #else - case .signalled(let signal): - str.append(contentsOf: "signalled(\(signal)): ") + case .signalled(let signal): + str.append(contentsOf: "signalled(\(signal)): ") #endif } @@ -1327,8 +1326,10 @@ extension AsyncProcessResult.Error: CustomStringConvertible { let indentation = " " str.append(contentsOf: " output:\n") str.append(contentsOf: indentation) - str.append(contentsOf: output.split(whereSeparator: { $0.isNewline }) - .joined(separator: "\n\(indentation)")) + str.append( + contentsOf: output.split(whereSeparator: { $0.isNewline }) + .joined(separator: "\n\(indentation)") + ) if !output.hasSuffix("\n") { str.append(contentsOf: "\n") } @@ -1340,21 +1341,21 @@ extension AsyncProcessResult.Error: CustomStringConvertible { } #if os(Windows) -extension FileHandle: WritableByteStream { - package var position: Int { - Int(offsetInFile) - } + extension FileHandle: WritableByteStream { + package var position: Int { + Int(offsetInFile) + } - package func write(_ byte: UInt8) { - self.write(Data([byte])) - } + package func write(_ byte: UInt8) { + self.write(Data([byte])) + } - package func write(_ bytes: some Collection) { - self.write(Data(bytes)) - } + package func write(_ bytes: some Collection) { + self.write(Data(bytes)) + } - package func flush() { - synchronizeFile() + package func flush() { + synchronizeFile() + } } -} #endif diff --git a/Sources/Basics/Concurrency/ConcurrencyHelpers.swift b/Sources/Basics/Concurrency/ConcurrencyHelpers.swift index 2837bea4b95..f06b944f203 100644 --- a/Sources/Basics/Concurrency/ConcurrencyHelpers.swift +++ b/Sources/Basics/Concurrency/ConcurrencyHelpers.swift @@ -20,7 +20,8 @@ import func TSCBasic.tsc_await public enum Concurrency { public static var maxOperations: Int { - Environment.current["SWIFTPM_MAX_CONCURRENT_OPERATIONS"].flatMap(Int.init) ?? ProcessInfo.processInfo + Environment.current["SWIFTPM_MAX_CONCURRENT_OPERATIONS"].flatMap(Int.init) + ?? ProcessInfo.processInfo .activeProcessorCount } } @@ -39,7 +40,6 @@ public func unsafe_await(_ body: @Sendable @escaping () async -> T) return box.get()! } - extension DispatchQueue { // a shared concurrent queue for running concurrent asynchronous operations public static let sharedConcurrent = DispatchQueue( @@ -63,7 +63,8 @@ extension DispatchQueue { package func asyncResult(_ callback: @escaping @Sendable (Result) -> Void, _ closure: @escaping @Sendable () async throws -> T) { let completion: @Sendable (Result) -> Void = { - result in self.async { + result in + self.async { callback(result) } } @@ -168,31 +169,31 @@ public final class AsyncOperationQueue: @unchecked Sendable { } switch waitingTasks[index] { - case .cancelled: - // If the task was cancelled in between creating the task cancellation handler and acquiring the lock, - // we should resume the continuation with a `CancellationError`. + case .cancelled: + // If the task was cancelled in between creating the task cancellation handler and acquiring the lock, + // we should resume the continuation with a `CancellationError`. + waitingTasks.remove(at: index) + return .cancel(continuation) + case .creating, .running, .waiting: + // A task may have completed since we initially checked if we should wait. Check again in this locked + // section and if we can start it, remove it from the waiting tasks and start it immediately. + if waitingTasks.count >= concurrentTasks { + waitingTasks[index] = .waiting(taskId, continuation) + return nil + } else { waitingTasks.remove(at: index) - return .cancel(continuation) - case .creating, .running, .waiting: - // A task may have completed since we initially checked if we should wait. Check again in this locked - // section and if we can start it, remove it from the waiting tasks and start it immediately. - if waitingTasks.count >= concurrentTasks { - waitingTasks[index] = .waiting(taskId, continuation) - return nil - } else { - waitingTasks.remove(at: index) - return .start(continuation) - } + return .start(continuation) + } } } switch action { - case .some(.cancel(let continuation)): - continuation.resume(throwing: _Concurrency.CancellationError()) - case .some(.start(let continuation)): - continuation.resume() - case .none: - return + case .some(.cancel(let continuation)): + continuation.resume(throwing: _Concurrency.CancellationError()) + case .some(.start(let continuation)): + continuation.resume() + case .none: + return } } } onCancel: { @@ -202,20 +203,20 @@ public final class AsyncOperationQueue: @unchecked Sendable { } switch self.waitingTasks[taskIndex] { - case .waiting(_, let continuation): - self.waitingTasks.remove(at: taskIndex) - - // If the parent task is cancelled then we need to manually handle resuming the - // continuation for the waiting task with a `CancellationError`. Return the continuation - // here so it can be resumed once the `waitingTasksLock` is released. - return continuation - case .creating, .running: - // If the task was still being created, mark it as cancelled in `waitingTasks` so that - // the handler for `withCheckedThrowingContinuation` can immediately cancel it. - self.waitingTasks[taskIndex] = .cancelled(taskId) - return nil - case .cancelled: - preconditionFailure("Attempting to cancel a task that was already cancelled") + case .waiting(_, let continuation): + self.waitingTasks.remove(at: taskIndex) + + // If the parent task is cancelled then we need to manually handle resuming the + // continuation for the waiting task with a `CancellationError`. Return the continuation + // here so it can be resumed once the `waitingTasksLock` is released. + return continuation + case .creating, .running: + // If the task was still being created, mark it as cancelled in `waitingTasks` so that + // the handler for `withCheckedThrowingContinuation` can immediately cancel it. + self.waitingTasks[taskIndex] = .cancelled(taskId) + return nil + case .cancelled: + preconditionFailure("Attempting to cancel a task that was already cancelled") } } diff --git a/Sources/Basics/Concurrency/ThreadSafeBox.swift b/Sources/Basics/Concurrency/ThreadSafeBox.swift index c05347a46ad..6df20482b58 100644 --- a/Sources/Basics/Concurrency/ThreadSafeBox.swift +++ b/Sources/Basics/Concurrency/ThreadSafeBox.swift @@ -30,7 +30,7 @@ public final class ThreadSafeBox { self.underlying = value } } - + public func mutate(body: (inout Value?) throws -> ()) rethrows { try self.lock.withLock { try body(&self.underlying) diff --git a/Sources/Basics/Concurrency/ThreadSafeKeyValueStore.swift b/Sources/Basics/Concurrency/ThreadSafeKeyValueStore.swift index c3bafbd1ea8..8af6bc019a7 100644 --- a/Sources/Basics/Concurrency/ThreadSafeKeyValueStore.swift +++ b/Sources/Basics/Concurrency/ThreadSafeKeyValueStore.swift @@ -57,8 +57,8 @@ public actor AsyncThrowingValueMemoizer { var stored: ValueStorage? enum ValueStorage { - case inProgress([CheckedContinuation]) - case complete(Result) + case inProgress([CheckedContinuation]) + case complete(Result) } public init() {} @@ -74,7 +74,7 @@ public actor AsyncThrowingValueMemoizer { } if case .inProgress(let array) = self.stored { self.stored = .complete(result) - array.forEach { $0.resume(with: result)} + array.forEach { $0.resume(with: result) } } return try result.get() } @@ -90,8 +90,6 @@ public actor AsyncThrowingValueMemoizer { } } - - /// Thread-safe dictionary like structure public final class ThreadSafeKeyValueStore where Key: Hashable { private var underlying: [Key: Value] @@ -112,7 +110,8 @@ public final class ThreadSafeKeyValueStore where Key: Hashable { self.lock.withLock { self.underlying[key] } - } set { + } + set { self.lock.withLock { self.underlying[key] = newValue } diff --git a/Sources/Basics/DispatchTimeInterval+Extensions.swift b/Sources/Basics/DispatchTimeInterval+Extensions.swift index 4c74b3bc61e..21f26f6e501 100644 --- a/Sources/Basics/DispatchTimeInterval+Extensions.swift +++ b/Sources/Basics/DispatchTimeInterval+Extensions.swift @@ -87,8 +87,8 @@ extension DispatchTimeInterval { case .never: return "n/a" #if canImport(Darwin) - @unknown default: - return "n/a" + @unknown default: + return "n/a" #endif } } @@ -96,12 +96,12 @@ extension DispatchTimeInterval { // remove when available to all platforms #if os(Linux) || os(Windows) || os(Android) || os(OpenBSD) || os(FreeBSD) -extension DispatchTime { - public func distance(to: DispatchTime) -> DispatchTimeInterval { - let final = to.uptimeNanoseconds - let point = self.uptimeNanoseconds - let duration = Int64(bitPattern: final.subtractingReportingOverflow(point).partialValue) - return .nanoseconds(duration >= Int.max ? Int.max : Int(duration)) + extension DispatchTime { + public func distance(to: DispatchTime) -> DispatchTimeInterval { + let final = to.uptimeNanoseconds + let point = self.uptimeNanoseconds + let duration = Int64(bitPattern: final.subtractingReportingOverflow(point).partialValue) + return .nanoseconds(duration >= Int.max ? Int.max : Int(duration)) + } } -} #endif diff --git a/Sources/Basics/Environment/Environment.swift b/Sources/Basics/Environment/Environment.swift index 59650363155..ed4e35b942e 100644 --- a/Sources/Basics/Environment/Environment.swift +++ b/Sources/Basics/Environment/Environment.swift @@ -13,16 +13,16 @@ import Foundation #if canImport(Glibc) -import Glibc + import Glibc #elseif canImport(Musl) -import Musl + import Musl #elseif os(Windows) -import CRT -import WinSDK + import CRT + import WinSDK #elseif canImport(Android) -import Android + import Android #else -import Darwin.C + import Darwin.C #endif // FIXME: Use Synchronization.Mutex when available @@ -108,9 +108,9 @@ extension Environment { package static var pathEntryDelimiter: String { #if os(Windows) - ";" + ";" #else - ":" + ":" #endif } } @@ -209,17 +209,17 @@ extension Environment { /// > Important: This operation is _not_ concurrency safe. package static func set(key: EnvironmentKey, value: String?) throws { #if os(Windows) - func _SetEnvironmentVariableW(_ key: String, _ value: String?) -> Bool { - key.withCString(encodedAs: UTF16.self) { key in - if let value { - value.withCString(encodedAs: UTF16.self) { value in - SetEnvironmentVariableW(key, value) + func _SetEnvironmentVariableW(_ key: String, _ value: String?) -> Bool { + key.withCString(encodedAs: UTF16.self) { key in + if let value { + value.withCString(encodedAs: UTF16.self) { value in + SetEnvironmentVariableW(key, value) + } + } else { + SetEnvironmentVariableW(key, nil) } - } else { - SetEnvironmentVariableW(key, nil) } } - } #endif // Invalidate cached value after mutating the global environment. @@ -229,47 +229,47 @@ extension Environment { defer { Self._cachedCurrent.withLock { $0 = nil } } if let value = value { #if os(Windows) - guard _SetEnvironmentVariableW(key.rawValue, value) else { - throw UpdateEnvironmentError( - function: "SetEnvironmentVariableW", - code: Int32(GetLastError()) - ) - } - guard _putenv("\(key)=\(value)") == 0 else { - throw UpdateEnvironmentError( - function: "_putenv", - code: Int32(GetLastError()) - ) - } + guard _SetEnvironmentVariableW(key.rawValue, value) else { + throw UpdateEnvironmentError( + function: "SetEnvironmentVariableW", + code: Int32(GetLastError()) + ) + } + guard _putenv("\(key)=\(value)") == 0 else { + throw UpdateEnvironmentError( + function: "_putenv", + code: Int32(GetLastError()) + ) + } #else - guard setenv(key.rawValue, value, 1) == 0 else { - throw UpdateEnvironmentError( - function: "setenv", - code: errno - ) - } + guard setenv(key.rawValue, value, 1) == 0 else { + throw UpdateEnvironmentError( + function: "setenv", + code: errno + ) + } #endif } else { #if os(Windows) - guard _SetEnvironmentVariableW(key.rawValue, nil) else { - throw UpdateEnvironmentError( - function: "SetEnvironmentVariableW", - code: Int32(GetLastError()) - ) - } - guard _putenv("\(key)=") == 0 else { - throw UpdateEnvironmentError( - function: "_putenv", - code: Int32(GetLastError()) - ) - } + guard _SetEnvironmentVariableW(key.rawValue, nil) else { + throw UpdateEnvironmentError( + function: "SetEnvironmentVariableW", + code: Int32(GetLastError()) + ) + } + guard _putenv("\(key)=") == 0 else { + throw UpdateEnvironmentError( + function: "_putenv", + code: Int32(GetLastError()) + ) + } #else - guard unsetenv(key.rawValue) == 0 else { - throw UpdateEnvironmentError( - function: "unsetenv", - code: errno - ) - } + guard unsetenv(key.rawValue) == 0 else { + throw UpdateEnvironmentError( + function: "unsetenv", + code: errno + ) + } #endif } } @@ -324,7 +324,8 @@ extension Environment: Collection { extension Environment: CustomStringConvertible { public var description: String { - let body = self + let body = + self .sorted { $0.key < $1.key } .map { "\"\($0.rawValue)=\($1)\"" } .joined(separator: ", ") diff --git a/Sources/Basics/Environment/EnvironmentKey.swift b/Sources/Basics/Environment/EnvironmentKey.swift index 8d31fcc4ab7..342dc5bdaf3 100644 --- a/Sources/Basics/Environment/EnvironmentKey.swift +++ b/Sources/Basics/Environment/EnvironmentKey.swift @@ -26,11 +26,11 @@ extension EnvironmentKey { package static var libraryPath: Self { #if os(Windows) - path + path #elseif canImport(Darwin) - "DYLD_LIBRARY_PATH" + "DYLD_LIBRARY_PATH" #else - "LD_LIBRARY_PATH" + "LD_LIBRARY_PATH" #endif } @@ -76,9 +76,9 @@ extension EnvironmentKey: Encodable { extension EnvironmentKey: Equatable { public static func == (_ lhs: Self, _ rhs: Self) -> Bool { #if os(Windows) - lhs.rawValue.lowercased() == rhs.rawValue.lowercased() + lhs.rawValue.lowercased() == rhs.rawValue.lowercased() #else - lhs.rawValue == rhs.rawValue + lhs.rawValue == rhs.rawValue #endif } } @@ -98,9 +98,9 @@ extension EnvironmentKey: Decodable { extension EnvironmentKey: Hashable { public func hash(into hasher: inout Hasher) { #if os(Windows) - self.rawValue.lowercased().hash(into: &hasher) + self.rawValue.lowercased().hash(into: &hasher) #else - self.rawValue.hash(into: &hasher) + self.rawValue.hash(into: &hasher) #endif } } diff --git a/Sources/Basics/FileSystem/AbsolutePath.swift b/Sources/Basics/FileSystem/AbsolutePath.swift index c472e5c0608..13a52075139 100644 --- a/Sources/Basics/FileSystem/AbsolutePath.swift +++ b/Sources/Basics/FileSystem/AbsolutePath.swift @@ -256,7 +256,7 @@ extension AbsolutePath { return nil } - var extensions = String(self.basename[firstDot ..< self.basename.endIndex]) + var extensions = String(self.basename[firstDot.. 1 else { return nil @@ -271,7 +271,7 @@ extension AbsolutePath { public var basenameWithoutAnyExtension: String { var basename = self.basename if let index = basename.firstIndex(of: ".") { - basename.removeSubrange(index ..< basename.endIndex) + basename.removeSubrange(index.. 0 + self.isFile($0) && !self.isSymlink($0) + && $0 + .extension != "lock" + && ((try? self.readFileContents($0)) ?? []).count > 0 } try handleExistingFiles(configurationFiles) } @@ -393,8 +395,10 @@ extension FileSystem { let configurationFiles = try self.getDirectoryContents(oldConfigDirectory) .map { oldConfigDirectory.appending(component: $0) } .filter { - self.isFile($0) && !self.isSymlink($0) && $0 - .extension != "lock" && ((try? self.readFileContents($0)) ?? []).count > 0 + self.isFile($0) && !self.isSymlink($0) + && $0 + .extension != "lock" + && ((try? self.readFileContents($0)) ?? []).count > 0 } try handleExistingFiles(configurationFiles) } @@ -452,10 +456,7 @@ extension FileSystem { // temporary 5.6, remove on next version: transition from ~/.swiftpm/security to idiomatic location + symbolic // link - if try idiomaticSecurityDirectory != self.dotSwiftPMSecurityDirectory && - self.exists(try self.dotSwiftPMSecurityDirectory) && - self.isDirectory(try self.dotSwiftPMSecurityDirectory) - { + if try idiomaticSecurityDirectory != self.dotSwiftPMSecurityDirectory && self.exists(try self.dotSwiftPMSecurityDirectory) && self.isDirectory(try self.dotSwiftPMSecurityDirectory) { try self.removeFileTree(self.dotSwiftPMSecurityDirectory) } // ~temporary 5.6 migration diff --git a/Sources/Basics/FileSystem/InMemoryFileSystem.swift b/Sources/Basics/FileSystem/InMemoryFileSystem.swift index 0853f607b31..1ffe4fbe6d3 100644 --- a/Sources/Basics/FileSystem/InMemoryFileSystem.swift +++ b/Sources/Basics/FileSystem/InMemoryFileSystem.swift @@ -23,7 +23,7 @@ public final class InMemoryFileSystem: FileSystem { private class Node { /// The actual node data. let contents: NodeContents - + /// Whether the node has executable bit enabled. var isExecutable: Bool @@ -415,10 +415,11 @@ public final class InMemoryFileSystem: FileSystem { return lock.withLock { // Ignore root and get the parent node's content if its a directory. guard !path.isRoot, - let parent = try? getNode(path.parentDirectory), - case .directory(let contents) = parent.contents else { - return - } + let parent = try? getNode(path.parentDirectory), + case .directory(let contents) = parent.contents + else { + return + } // Set it to nil to release the contents. contents.entries[path.basename] = nil } @@ -500,9 +501,9 @@ public final class InMemoryFileSystem: FileSystem { } } - return try fileQueue.sync(flags: type == .exclusive ? .barrier : .init() , execute: body) + return try fileQueue.sync(flags: type == .exclusive ? .barrier : .init(), execute: body) } - + public func withLock(on path: TSCBasic.AbsolutePath, type: FileLock.LockType, blocking: Bool, _ body: () throws -> T) throws -> T { try self.withLock(on: path, type: type, body) } diff --git a/Sources/Basics/FileSystem/TSCAdapters.swift b/Sources/Basics/FileSystem/TSCAdapters.swift index 203c359b04c..7963e1f363c 100644 --- a/Sources/Basics/FileSystem/TSCAdapters.swift +++ b/Sources/Basics/FileSystem/TSCAdapters.swift @@ -27,7 +27,8 @@ public func resolveSymlinks(_ path: AbsolutePath) throws -> AbsolutePath { } public func withTemporaryDirectory( - dir: AbsolutePath? = nil, prefix: String = "TemporaryDirectory", + dir: AbsolutePath? = nil, + prefix: String = "TemporaryDirectory", _ body: (AbsolutePath, @escaping (AbsolutePath) -> Void) throws -> Result ) throws -> Result { try TSCBasic.withTemporaryDirectory(dir: dir?.underlying, prefix: prefix) { path, callback in @@ -39,7 +40,8 @@ public func withTemporaryDirectory( } public func withTemporaryDirectory( - dir: AbsolutePath? = nil, prefix: String = "TemporaryDirectory", + dir: AbsolutePath? = nil, + prefix: String = "TemporaryDirectory", _ body: (AbsolutePath, @escaping (AbsolutePath) async -> Void) async throws -> Result ) async throws -> Result { try await TSCBasic.withTemporaryDirectory(dir: dir?.underlying, prefix: prefix) { path, callback in @@ -51,7 +53,9 @@ public func withTemporaryDirectory( } public func withTemporaryDirectory( - dir: AbsolutePath? = nil, prefix: String = "TemporaryDirectory", removeTreeOnDeinit: Bool = false, + dir: AbsolutePath? = nil, + prefix: String = "TemporaryDirectory", + removeTreeOnDeinit: Bool = false, _ body: (AbsolutePath) throws -> Result ) throws -> Result { try TSCBasic.withTemporaryDirectory(dir: dir?.underlying, prefix: prefix, removeTreeOnDeinit: removeTreeOnDeinit) { @@ -60,7 +64,9 @@ public func withTemporaryDirectory( } public func withTemporaryDirectory( - dir: AbsolutePath? = nil, prefix: String = "TemporaryDirectory", removeTreeOnDeinit: Bool = false, + dir: AbsolutePath? = nil, + prefix: String = "TemporaryDirectory", + removeTreeOnDeinit: Bool = false, _ body: (AbsolutePath) async throws -> Result ) async throws -> Result { try await TSCBasic.withTemporaryDirectory( diff --git a/Sources/Basics/FileSystem/TemporaryFile.swift b/Sources/Basics/FileSystem/TemporaryFile.swift index a9f253b6f08..46516340cfa 100644 --- a/Sources/Basics/FileSystem/TemporaryFile.swift +++ b/Sources/Basics/FileSystem/TemporaryFile.swift @@ -89,7 +89,7 @@ private func createTemporaryDirectory( // it is more or less equal to generation using `mkdtemp` function let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - let randomSuffix = String((0 ..< 6).map { _ in letters.randomElement()! }) + let randomSuffix = String((0..<6).map { _ in letters.randomElement()! }) let tempDirectory = try dir ?? fileSystem.tempDirectory guard fileSystem.isDirectory(tempDirectory) else { diff --git a/Sources/Basics/FileSystem/VirtualFileSystem.swift b/Sources/Basics/FileSystem/VirtualFileSystem.swift index ca485b1be3c..0dbf15e1921 100644 --- a/Sources/Basics/FileSystem/VirtualFileSystem.swift +++ b/Sources/Basics/FileSystem/VirtualFileSystem.swift @@ -116,7 +116,7 @@ extension FileSystem { contents: contents ) } else if isDirectory(current) { - if $0.hasPrefix(".") { return nil } // we ignore hidden files + if $0.hasPrefix(".") { return nil } // we ignore hidden files return .directory( name: $0, isSymlink: isSymlink, diff --git a/Sources/Basics/Graph/AdjacencyMatrix.swift b/Sources/Basics/Graph/AdjacencyMatrix.swift index 9326d499a7c..9a44ae1e982 100644 --- a/Sources/Basics/Graph/AdjacencyMatrix.swift +++ b/Sources/Basics/Graph/AdjacencyMatrix.swift @@ -30,7 +30,7 @@ struct AdjacencyMatrix { init(rows: Int, columns: Int) { self.columns = columns self.rows = rows - + let (quotient, remainder) = (rows * columns).quotientAndRemainder(dividingBy: 8) self.bytes = .init(repeating: 0, count: quotient + (remainder > 0 ? 1 : 0)) } diff --git a/Sources/Basics/Graph/DirectedGraph.swift b/Sources/Basics/Graph/DirectedGraph.swift index 4e58b5a2a76..1e5b1d5bffb 100644 --- a/Sources/Basics/Graph/DirectedGraph.swift +++ b/Sources/Basics/Graph/DirectedGraph.swift @@ -26,7 +26,7 @@ public struct DirectedGraph { public mutating func addEdge(source: Int, destination: Int) { self.edges[source].append(destination) } - + /// Checks whether a path via previously created edges between two given nodes exists. /// - Parameters: /// - source: `Index` of a node to start traversing edges from. diff --git a/Sources/Basics/HTTPClient/HTTPClient.swift b/Sources/Basics/HTTPClient/HTTPClient.swift index d5c308ef4d3..12128d788af 100644 --- a/Sources/Basics/HTTPClient/HTTPClient.swift +++ b/Sources/Basics/HTTPClient/HTTPClient.swift @@ -86,8 +86,8 @@ public actor HTTPClient { } if let authorization = request.options.authorizationProvider?(request.url), - !authorization.isEmpty, - !request.headers.contains("Authorization") + !authorization.isEmpty, + !request.headers.contains("Authorization") { request.headers.add(name: "Authorization", value: authorization) } @@ -161,7 +161,7 @@ public actor HTTPClient { } // check for valid response codes if let validResponseCodes = request.options.validResponseCodes, - !validResponseCodes.contains(response.statusCode) + !validResponseCodes.contains(response.statusCode) { throw HTTPClientError.badResponseStatusCode(response.statusCode) } else { @@ -187,7 +187,7 @@ public actor HTTPClient { } let exponential = Int(min(pow(2.0, Double(requestNumber)), Double(Int.max))) let delayMilli = exponential.multipliedReportingOverflow(by: delay.milliseconds() ?? 0).partialValue - let jitterMilli = Int.random(in: 1 ... 10) + let jitterMilli = Int.random(in: 1...10) return .milliseconds(delayMilli + jitterMilli) } } diff --git a/Sources/Basics/HTTPClient/LegacyHTTPClient.swift b/Sources/Basics/HTTPClient/LegacyHTTPClient.swift index e47efe68203..e0c416941b1 100644 --- a/Sources/Basics/HTTPClient/LegacyHTTPClient.swift +++ b/Sources/Basics/HTTPClient/LegacyHTTPClient.swift @@ -108,8 +108,8 @@ public final class LegacyHTTPClient: Cancellable { } if let authorization = request.options.authorizationProvider?(request.url), - !authorization.isEmpty, - !request.headers.contains("Authorization") + !authorization.isEmpty, + !request.headers.contains("Authorization") { request.headers.add(name: "Authorization", value: authorization) } @@ -238,7 +238,7 @@ public final class LegacyHTTPClient: Cancellable { } // check for valid response codes if let validResponseCodes = request.options.validResponseCodes, - !validResponseCodes.contains(response.statusCode) + !validResponseCodes.contains(response.statusCode) { return completion(.failure(HTTPClientError.badResponseStatusCode(response.statusCode))) } @@ -261,7 +261,7 @@ public final class LegacyHTTPClient: Cancellable { } let exponential = Int(min(pow(2.0, Double(requestNumber)), Double(Int.max))) let delayMilli = exponential.multipliedReportingOverflow(by: delay.milliseconds() ?? 0).partialValue - let jitterMilli = Int.random(in: 1 ... 10) + let jitterMilli = Int.random(in: 1...10) return .milliseconds(delayMilli + jitterMilli) } } diff --git a/Sources/Basics/HTTPClient/URLSessionHTTPClient.swift b/Sources/Basics/HTTPClient/URLSessionHTTPClient.swift index a12c352f725..5d28514fa2c 100644 --- a/Sources/Basics/HTTPClient/URLSessionHTTPClient.swift +++ b/Sources/Basics/HTTPClient/URLSessionHTTPClient.swift @@ -14,8 +14,8 @@ import _Concurrency import Foundation import struct TSCUtility.Versioning #if canImport(FoundationNetworking) -// FIXME: this brings OpenSSL dependency on Linux and needs to be replaced with `swift-server/async-http-client` package -import FoundationNetworking + // FIXME: this brings OpenSSL dependency on Linux and needs to be replaced with `swift-server/async-http-client` package + import FoundationNetworking #endif final class URLSessionHTTPClient: Sendable { @@ -212,7 +212,7 @@ private final class DataTaskManager: NSObject, URLSessionDataDelegate { var request = request // Set `Authorization` header for the redirected request if let redirectURL = request.url, let authorization = task.authorizationProvider?(redirectURL), - request.value(forHTTPHeaderField: "Authorization") == nil + request.value(forHTTPHeaderField: "Authorization") == nil { request.addValue(authorization, forHTTPHeaderField: "Authorization") } @@ -285,8 +285,7 @@ private final class DownloadTaskManager: NSObject, URLSessionDownloadDelegate { return } - let totalBytesToDownload = totalBytesExpectedToWrite != NSURLSessionTransferSizeUnknown ? - totalBytesExpectedToWrite : nil + let totalBytesToDownload = totalBytesExpectedToWrite != NSURLSessionTransferSizeUnknown ? totalBytesExpectedToWrite : nil do { try task.progressHandler?(totalBytesWritten, totalBytesToDownload) @@ -420,9 +419,11 @@ extension URLRequest { extension HTTPURLResponse { fileprivate func response(body: Data?) -> HTTPClientResponse { - let headers = HTTPClientHeaders(self.allHeaderFields.map { header in - .init(name: "\(header.key)", value: "\(header.value)") - }) + let headers = HTTPClientHeaders( + self.allHeaderFields.map { header in + .init(name: "\(header.key)", value: "\(header.value)") + } + ) return HTTPClientResponse( statusCode: self.statusCode, statusText: Self.localizedString(forStatusCode: self.statusCode), diff --git a/Sources/Basics/ImportScanning.swift b/Sources/Basics/ImportScanning.swift index bd4b4576217..5e84ccbca10 100644 --- a/Sources/Basics/ImportScanning.swift +++ b/Sources/Basics/ImportScanning.swift @@ -14,8 +14,10 @@ import Dispatch import class Foundation.JSONDecoder -private let defaultImports = ["Swift", "SwiftOnoneSupport", "_Concurrency", - "_StringProcessing", "_SwiftConcurrencyShims"] +private let defaultImports = [ + "Swift", "SwiftOnoneSupport", "_Concurrency", + "_StringProcessing", "_SwiftConcurrencyShims", +] private struct Imports: Decodable { let imports: [String] @@ -41,9 +43,12 @@ public struct SwiftcImportScanner: ImportScanner { } public func scanImports(_ filePathToScan: AbsolutePath) async throws -> [String] { - let cmd = [swiftCompilerPath.pathString, - filePathToScan.pathString, - "-scan-dependencies", "-Xfrontend", "-import-prescan"] + self.swiftCompilerFlags + let cmd = + [ + swiftCompilerPath.pathString, + filePathToScan.pathString, + "-scan-dependencies", "-Xfrontend", "-import-prescan", + ] + self.swiftCompilerFlags let result = try await AsyncProcess.popen(arguments: cmd, environment: self.swiftCompilerEnvironment) diff --git a/Sources/Basics/Netrc.swift b/Sources/Basics/Netrc.swift index cbe88206895..7156b359a22 100644 --- a/Sources/Basics/Netrc.swift +++ b/Sources/Basics/Netrc.swift @@ -27,8 +27,10 @@ public struct Netrc: Sendable { /// - Parameters: /// - url: The url to retrieve authorization information for. public func authorization(for url: URL) -> Authorization? { - guard let index = machines.firstIndex(where: { $0.name == url.host }) ?? machines - .firstIndex(where: { $0.isDefault }) + guard + let index = machines.firstIndex(where: { $0.name == url.host }) + ?? machines + .firstIndex(where: { $0.isDefault }) else { return .none } @@ -53,8 +55,10 @@ public struct Netrc: Sendable { } init?(for match: NSTextCheckingResult, string: String, variant: String = "") { - guard let name = RegexUtil.Token.machine.capture(in: match, string: string) ?? RegexUtil.Token.default - .capture(in: match, string: string), + guard + let name = RegexUtil.Token.machine.capture(in: match, string: string) + ?? RegexUtil.Token.default + .capture(in: match, string: string), let login = RegexUtil.Token.login.capture(prefix: variant, in: match, string: string), let password = RegexUtil.Token.password.capture(prefix: variant, in: match, string: string) else { @@ -103,11 +107,12 @@ public struct NetrcParser { let matches = regex.matches( in: content, options: [], - range: NSRange(content.startIndex ..< content.endIndex, in: content) + range: NSRange(content.startIndex..( - _ animation: ProgressAnimationProtocol, - now: @escaping () -> C.Instant, interval: C.Duration, clock: C.Type = C.self + _ animation: ProgressAnimationProtocol, + now: @escaping () -> C.Instant, + interval: C.Duration, + clock: C.Type = C.self ) { self.animation = animation var lastUpdate: C.Instant? @@ -79,7 +81,7 @@ extension ProgressAnimationProtocol { @_spi(SwiftPMInternal) public func throttled( interval: ContinuousClock.Duration - ) -> some ProgressAnimationProtocol { + ) -> some ProgressAnimationProtocol { self.throttled(clock: ContinuousClock(), interval: interval) } } diff --git a/Sources/Basics/SQLite.swift b/Sources/Basics/SQLite.swift index cab2374f3c3..1964e478095 100644 --- a/Sources/Basics/SQLite.swift +++ b/Sources/Basics/SQLite.swift @@ -14,17 +14,17 @@ import TSCBasic import Foundation #if SWIFT_PACKAGE && (os(Windows) || os(Android)) -#if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import SwiftToolchainCSQLite + #if USE_IMPL_ONLY_IMPORTS + @_implementationOnly import SwiftToolchainCSQLite + #else + import SwiftToolchainCSQLite + #endif #else -import SwiftToolchainCSQLite -#endif -#else -#if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import SPMSQLite3 -#else -import SPMSQLite3 -#endif + #if USE_IMPL_ONLY_IMPORTS + @_implementationOnly import SPMSQLite3 + #else + import SPMSQLite3 + #endif #endif /// A minimal SQLite wrapper. @@ -128,7 +128,8 @@ package final class SQLite { package var busyTimeoutSeconds: Int32 { get { self._busyTimeoutSeconds - } set { + } + set { self._busyTimeoutSeconds = newValue } } @@ -137,7 +138,8 @@ package final class SQLite { internal var _busyTimeoutSeconds: Int32 { get { Int32(truncatingIfNeeded: Int(Double(self.busyTimeoutMilliseconds) / 1000)) - } set { + } + set { self.busyTimeoutMilliseconds = newValue * 1000 } } @@ -325,7 +327,7 @@ private func sqlite_callback( let numColumns = Int(numColumns) var result: [SQLite.Column] = [] - for idx in 0 ..< numColumns { + for idx in 0..: Closable { observabilityScope? .emit( warning: """ - truncating \(self.tableName) cache database since it reached max size of \( - self.configuration.maxSizeInBytes ?? 0 - ) bytes - """ + truncating \(self.tableName) cache database since it reached max size of \( + self.configuration.maxSizeInBytes ?? 0 + ) bytes + """ ) try self.executeStatement("DELETE FROM \(self.tableName);") { statement in try statement.step() @@ -224,11 +224,11 @@ package final class SQLiteBackedCache: Closable { private func createSchemaIfNecessary(db: SQLite) throws { let table = """ - CREATE TABLE IF NOT EXISTS \(self.tableName) ( - key STRING PRIMARY KEY NOT NULL, - value BLOB NOT NULL - ); - """ + CREATE TABLE IF NOT EXISTS \(self.tableName) ( + key STRING PRIMARY KEY NOT NULL, + value BLOB NOT NULL + ); + """ try db.exec(query: table) try db.exec(query: "PRAGMA journal_mode=WAL;") diff --git a/Sources/Basics/Sandbox.swift b/Sources/Basics/Sandbox.swift index f24636cac13..0b27107c600 100644 --- a/Sources/Basics/Sandbox.swift +++ b/Sources/Basics/Sandbox.swift @@ -57,17 +57,17 @@ public enum Sandbox { allowNetworkConnections: [SandboxNetworkPermission] = [] ) throws -> [String] { #if os(macOS) - let profile = try macOSSandboxProfile( - fileSystem: fileSystem, - strictness: strictness, - writableDirectories: writableDirectories, - readOnlyDirectories: readOnlyDirectories, - allowNetworkConnections: allowNetworkConnections - ) - return ["/usr/bin/sandbox-exec", "-p", profile] + command + let profile = try macOSSandboxProfile( + fileSystem: fileSystem, + strictness: strictness, + writableDirectories: writableDirectories, + readOnlyDirectories: readOnlyDirectories, + allowNetworkConnections: allowNetworkConnections + ) + return ["/usr/bin/sandbox-exec", "-p", profile] + command #else - // rdar://40235432, rdar://75636874 tracks implementing sandboxes for other platforms. - return command + // rdar://40235432, rdar://75636874 tracks implementing sandboxes for other platforms. + return command #endif } @@ -76,7 +76,7 @@ public enum Sandbox { /// Blocks network access and all file system modifications. case `default` /// More lenient restrictions than the default, for compatibility with SwiftPM manifests using a tools version older than 5.3. - case manifest_pre_53 // backwards compatibility for manifests + case manifest_pre_53 // backwards compatibility for manifests /// Like `default`, but also makes temporary-files directories (such as `/tmp`) on the platform writable. case writableTemporaryDirectory } @@ -85,174 +85,175 @@ public enum Sandbox { // MARK: - macOS #if os(macOS) -fileprivate let threadSafeDarwinCacheDirectories: [AbsolutePath] = { - func GetConfStr(_ name: CInt) -> AbsolutePath? { - let length: Int = confstr(name, nil, 0) + fileprivate let threadSafeDarwinCacheDirectories: [AbsolutePath] = { + func GetConfStr(_ name: CInt) -> AbsolutePath? { + let length: Int = confstr(name, nil, 0) - let buffer: UnsafeMutableBufferPointer = .allocate(capacity: length) - defer { buffer.deallocate() } + let buffer: UnsafeMutableBufferPointer = .allocate(capacity: length) + defer { buffer.deallocate() } - guard confstr(name, buffer.baseAddress, length) == length else { return nil } + guard confstr(name, buffer.baseAddress, length) == length else { return nil } - let value = String(cString: buffer.baseAddress!) - guard value.hasSuffix("/") else { return nil } + let value = String(cString: buffer.baseAddress!) + guard value.hasSuffix("/") else { return nil } - return try? resolveSymlinks(AbsolutePath(validating: value)) - } + return try? resolveSymlinks(AbsolutePath(validating: value)) + } - var directories: [AbsolutePath] = [] - try? directories.append(AbsolutePath(validating: "/private/var/tmp")) - (try? TSCBasic.determineTempDirectory()).map { directories.append(AbsolutePath($0)) } - GetConfStr(_CS_DARWIN_USER_TEMP_DIR).map { directories.append($0) } - GetConfStr(_CS_DARWIN_USER_CACHE_DIR).map { directories.append($0) } - return directories -}() - -fileprivate func macOSSandboxProfile( - fileSystem: FileSystem, - strictness: Sandbox.Strictness, - writableDirectories: [AbsolutePath], - readOnlyDirectories: [AbsolutePath], - allowNetworkConnections: [SandboxNetworkPermission] -) throws -> String { - var contents = "(version 1)\n" - - // Deny everything by default. - contents += "(deny default)\n" - - // Import the system sandbox profile. - contents += "(import \"system.sb\")\n" - - // Allow reading all files; ideally we'd only allow the package directory and any dependencies, - // but all kinds of system locations need to be accessible. - contents += "(allow file-read*)\n" - - // This is needed to launch any processes. - contents += "(allow process*)\n" - - // This is needed to use the UniformTypeIdentifiers API. - contents += "(allow mach-lookup (global-name \"com.apple.lsd.mapdb\"))\n" - - // For downloadable Metal toolchain lookups. - contents += "(allow mach-lookup (global-name \"com.apple.mobileassetd.v2\"))\n" - - if allowNetworkConnections.filter({ $0 != .none }).isEmpty == false { - // this is used by the system for caching purposes and will lead to log spew if not allowed - contents += "(allow file-write* (regex \"/Users/*/Library/Caches/*/Cache.db*\"))" - - // this allows the specific network connections, as well as resolving DNS - contents += """ - (system-network) - (allow network-outbound - (literal "/private/var/run/mDNSResponder") - """ - - allowNetworkConnections.forEach { - if let domain = $0.domain { - $0.ports.forEach { port in - contents += "(remote ip \"\(domain):\(port)\")" + var directories: [AbsolutePath] = [] + try? directories.append(AbsolutePath(validating: "/private/var/tmp")) + (try? TSCBasic.determineTempDirectory()).map { directories.append(AbsolutePath($0)) } + GetConfStr(_CS_DARWIN_USER_TEMP_DIR).map { directories.append($0) } + GetConfStr(_CS_DARWIN_USER_CACHE_DIR).map { directories.append($0) } + return directories + }() + + fileprivate func macOSSandboxProfile( + fileSystem: FileSystem, + strictness: Sandbox.Strictness, + writableDirectories: [AbsolutePath], + readOnlyDirectories: [AbsolutePath], + allowNetworkConnections: [SandboxNetworkPermission] + ) throws -> String { + var contents = "(version 1)\n" + + // Deny everything by default. + contents += "(deny default)\n" + + // Import the system sandbox profile. + contents += "(import \"system.sb\")\n" + + // Allow reading all files; ideally we'd only allow the package directory and any dependencies, + // but all kinds of system locations need to be accessible. + contents += "(allow file-read*)\n" + + // This is needed to launch any processes. + contents += "(allow process*)\n" + + // This is needed to use the UniformTypeIdentifiers API. + contents += "(allow mach-lookup (global-name \"com.apple.lsd.mapdb\"))\n" + + // For downloadable Metal toolchain lookups. + contents += "(allow mach-lookup (global-name \"com.apple.mobileassetd.v2\"))\n" + + if allowNetworkConnections.filter({ $0 != .none }).isEmpty == false { + // this is used by the system for caching purposes and will lead to log spew if not allowed + contents += "(allow file-write* (regex \"/Users/*/Library/Caches/*/Cache.db*\"))" + + // this allows the specific network connections, as well as resolving DNS + contents += """ + (system-network) + (allow network-outbound + (literal "/private/var/run/mDNSResponder") + """ + + allowNetworkConnections.forEach { + if let domain = $0.domain { + $0.ports.forEach { port in + contents += "(remote ip \"\(domain):\(port)\")" + } + + // empty list of ports means all are permitted + if $0.ports.isEmpty { + contents += "(remote ip \"\(domain):*\")" + } } - // empty list of ports means all are permitted - if $0.ports.isEmpty { - contents += "(remote ip \"\(domain):*\")" + switch $0 { + case .docker: + // specifically allow Docker by basename of the socket + contents += "(remote unix-socket (regex \"*/docker.sock\"))" + case .unixDomainSocket: + // this allows unix domain sockets + contents += "(remote unix-socket)" + default: + break } } - switch $0 { - case .docker: - // specifically allow Docker by basename of the socket - contents += "(remote unix-socket (regex \"*/docker.sock\"))" - case .unixDomainSocket: - // this allows unix domain sockets - contents += "(remote unix-socket)" - default: - break - } + contents += "\n)\n" } - contents += "\n)\n" - } - - // The following accesses are only needed when interpreting the manifest (versus running a compiled version). - if strictness == .manifest_pre_53 { - // This is required by the Swift compiler. - contents += "(allow sysctl*)\n" - } + // The following accesses are only needed when interpreting the manifest (versus running a compiled version). + if strictness == .manifest_pre_53 { + // This is required by the Swift compiler. + contents += "(allow sysctl*)\n" + } - // Allow writing only to certain directories. - var writableDirectoriesExpression: [String] = [] + // Allow writing only to certain directories. + var writableDirectoriesExpression: [String] = [] - // The following accesses are only needed when interpreting the manifest (versus running a compiled version). - if strictness == .manifest_pre_53 { - writableDirectoriesExpression += threadSafeDarwinCacheDirectories.map { - ##"(regex #"^\##($0.pathString)/org\.llvm\.clang.*")"## + // The following accesses are only needed when interpreting the manifest (versus running a compiled version). + if strictness == .manifest_pre_53 { + writableDirectoriesExpression += threadSafeDarwinCacheDirectories.map { + ##"(regex #"^\##($0.pathString)/org\.llvm\.clang.*")"## + } } - } - // Optionally allow writing to temporary directories (a lot of use of Foundation requires this). - else if strictness == .writableTemporaryDirectory { - var stableCacheDirectories: [AbsolutePath] = [] - // Add `subpath` expressions for the regular, Foundation and clang module cache temporary directories. - for tmpDir in (["/tmp"] + threadSafeDarwinCacheDirectories.map(\.pathString)) { - let resolved = try resolveSymlinks(AbsolutePath(validating: tmpDir)) - if !stableCacheDirectories.contains(where: { $0.isAncestorOfOrEqual(to: resolved) }) { - stableCacheDirectories.append(resolved) - writableDirectoriesExpression += [ - "(subpath \(resolved.quotedAsSubpathForSandboxProfile))", - ] + // Optionally allow writing to temporary directories (a lot of use of Foundation requires this). + else if strictness == .writableTemporaryDirectory { + var stableCacheDirectories: [AbsolutePath] = [] + // Add `subpath` expressions for the regular, Foundation and clang module cache temporary directories. + for tmpDir in (["/tmp"] + threadSafeDarwinCacheDirectories.map(\.pathString)) { + let resolved = try resolveSymlinks(AbsolutePath(validating: tmpDir)) + if !stableCacheDirectories.contains(where: { $0.isAncestorOfOrEqual(to: resolved) }) { + stableCacheDirectories.append(resolved) + writableDirectoriesExpression += [ + "(subpath \(resolved.quotedAsSubpathForSandboxProfile))" + ] + } } } - } - // Emit rules for paths under which writing is allowed. Some of these expressions may be regular expressions and others literal subpaths. - if writableDirectoriesExpression.count > 0 { - contents += "(allow file-write*\n" - for expression in writableDirectoriesExpression { - contents += " \(expression)\n" + // Emit rules for paths under which writing is allowed. Some of these expressions may be regular expressions and others literal subpaths. + if writableDirectoriesExpression.count > 0 { + contents += "(allow file-write*\n" + for expression in writableDirectoriesExpression { + contents += " \(expression)\n" + } + contents += ")\n" } - contents += ")\n" - } - // Emit rules for paths under which writing should be disallowed, even if they would be covered by a previous rule to allow writing to them. A classic case is a package which is located under the temporary directory, which should be read-only even though the temporary directory as a whole is writable. - if readOnlyDirectories.count > 0 { - contents += "(deny file-write*\n" - for path in readOnlyDirectories { - contents += " (subpath \(try resolveSymlinks(path).quotedAsSubpathForSandboxProfile))\n" + // Emit rules for paths under which writing should be disallowed, even if they would be covered by a previous rule to allow writing to them. A classic case is a package which is located under the temporary directory, which should be read-only even though the temporary directory as a whole is writable. + if readOnlyDirectories.count > 0 { + contents += "(deny file-write*\n" + for path in readOnlyDirectories { + contents += " (subpath \(try resolveSymlinks(path).quotedAsSubpathForSandboxProfile))\n" + } + contents += ")\n" } - contents += ")\n" - } - // Emit rules for paths under which writing is allowed, even if they are descendants directories that are otherwise read-only. - if writableDirectories.count > 0 { - contents += "(allow file-write*\n" - var stableItemReplacementDirectories: [AbsolutePath] = [] - for path in writableDirectories { - contents += " (subpath \(try resolveSymlinks(path).quotedAsSubpathForSandboxProfile))\n" - - // `itemReplacementDirectories` may return a combination of stable directory paths, and subdirectories which are unique on every call. Avoid including unnecessary subdirectories in the Sandbox profile which may lead to nondeterminism in its construction. - if let itemReplacementDirectories = try? fileSystem.itemReplacementDirectories(for: path).sorted(by: { $0.pathString.count < $1.pathString.count }) { - for directory in itemReplacementDirectories { - let resolved = try resolveSymlinks(directory) - if !stableItemReplacementDirectories.contains(where: { $0.isAncestorOfOrEqual(to: resolved) }) { - stableItemReplacementDirectories.append(resolved) - contents += " (subpath \(resolved.quotedAsSubpathForSandboxProfile))\n" + // Emit rules for paths under which writing is allowed, even if they are descendants directories that are otherwise read-only. + if writableDirectories.count > 0 { + contents += "(allow file-write*\n" + var stableItemReplacementDirectories: [AbsolutePath] = [] + for path in writableDirectories { + contents += " (subpath \(try resolveSymlinks(path).quotedAsSubpathForSandboxProfile))\n" + + // `itemReplacementDirectories` may return a combination of stable directory paths, and subdirectories which are unique on every call. Avoid including unnecessary subdirectories in the Sandbox profile which may lead to nondeterminism in its construction. + if let itemReplacementDirectories = try? fileSystem.itemReplacementDirectories(for: path).sorted(by: { $0.pathString.count < $1.pathString.count }) { + for directory in itemReplacementDirectories { + let resolved = try resolveSymlinks(directory) + if !stableItemReplacementDirectories.contains(where: { $0.isAncestorOfOrEqual(to: resolved) }) { + stableItemReplacementDirectories.append(resolved) + contents += " (subpath \(resolved.quotedAsSubpathForSandboxProfile))\n" + } } } } + contents += ")\n" } - contents += ")\n" - } - return contents -} + return contents + } -extension AbsolutePath { - /// Private computed property that returns a version of the path as a string quoted for use as a subpath in a .sb sandbox profile. - fileprivate var quotedAsSubpathForSandboxProfile: String { - "\"" + self.pathString - .replacing("\\", with: "\\\\") - .replacing("\"", with: "\\\"") - + "\"" + extension AbsolutePath { + /// Private computed property that returns a version of the path as a string quoted for use as a subpath in a .sb sandbox profile. + fileprivate var quotedAsSubpathForSandboxProfile: String { + "\"" + + self.pathString + .replacing("\\", with: "\\\\") + .replacing("\"", with: "\\\"") + + "\"" + } } -} #endif diff --git a/Sources/Basics/SwiftVersion.swift b/Sources/Basics/SwiftVersion.swift index 6b0f6599882..4c5847546f7 100644 --- a/Sources/Basics/SwiftVersion.swift +++ b/Sources/Basics/SwiftVersion.swift @@ -11,9 +11,9 @@ //===----------------------------------------------------------------------===// #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import TSCclibc + @_implementationOnly import TSCclibc #else -private import TSCclibc + private import TSCclibc #endif public struct SwiftVersion: Sendable { diff --git a/Sources/Basics/TestingLibrary.swift b/Sources/Basics/TestingLibrary.swift index 289774ca673..4884ffeb6ad 100644 --- a/Sources/Basics/TestingLibrary.swift +++ b/Sources/Basics/TestingLibrary.swift @@ -12,22 +12,21 @@ /// The testing libraries supported by the package manager. public enum TestingLibrary: Sendable, CustomStringConvertible { - /// The XCTest library. - /// - /// This case represents both the open-source swift-corelibs-xctest - /// package and Apple's XCTest framework that ships with Xcode. - case xctest + /// The XCTest library. + /// + /// This case represents both the open-source swift-corelibs-xctest + /// package and Apple's XCTest framework that ships with Xcode. + case xctest - /// The swift-testing library. - case swiftTesting + /// The swift-testing library. + case swiftTesting - public var description: String { - switch self { - case .xctest: - "XCTest" - case .swiftTesting: - "Swift Testing" + public var description: String { + switch self { + case .xctest: + "XCTest" + case .swiftTesting: + "Swift Testing" + } } - } } - diff --git a/Sources/Basics/Triple+Basics.swift b/Sources/Basics/Triple+Basics.swift index e1f33bd31dc..dfb4b3d2459 100644 --- a/Sources/Basics/Triple+Basics.swift +++ b/Sources/Basics/Triple+Basics.swift @@ -162,7 +162,7 @@ extension Triple { case .wasi: return ".wasm" default: - break + break } guard let objectFormat = self.objectFormat else { @@ -228,12 +228,7 @@ extension Triple { return true } - if - self.arch == triple.arch && - self.vendor == triple.vendor && - self.os == triple.os && - self.environment == triple.environment - { + if self.arch == triple.arch && self.vendor == triple.vendor && self.os == triple.os && self.environment == triple.environment { return self.osVersion >= triple.osVersion } else { return false @@ -246,11 +241,11 @@ extension Triple: CustomStringConvertible { } extension Triple: Equatable { - public static func ==(lhs: Triple, rhs: Triple) -> Bool { - lhs.arch == rhs.arch - && lhs.vendor == rhs.vendor - && lhs.os == rhs.os - && lhs.environment == rhs.environment - && lhs.osVersion == rhs.osVersion + public static func == (lhs: Triple, rhs: Triple) -> Bool { + lhs.arch == rhs.arch + && lhs.vendor == rhs.vendor + && lhs.os == rhs.os + && lhs.environment == rhs.environment + && lhs.osVersion == rhs.osVersion } } diff --git a/Sources/Basics/Vendor/Triple+Platforms.swift b/Sources/Basics/Vendor/Triple+Platforms.swift index d26931b0ca7..e17784bae2d 100644 --- a/Sources/Basics/Vendor/Triple+Platforms.swift +++ b/Sources/Basics/Vendor/Triple+Platforms.swift @@ -30,410 +30,409 @@ /// `Triple.version(for:)` retrieves a version based on the /// corresponding `DarwinPlatform`. public enum DarwinPlatform: Hashable { - /// macOS, corresponding to the `macosx`, `macos`, and `darwin` OS names. - case macOS - - /// iOS, corresponding to the `ios` and `iphoneos` OS names. This does not - /// match tvOS. - case iOS(Environment) - - /// tvOS, corresponding to the `tvos` OS name. - case tvOS(EnvironmentWithoutCatalyst) - - /// watchOS, corresponding to the `watchos` OS name. - case watchOS(EnvironmentWithoutCatalyst) - - /// The most general form of environment information attached to a - /// `DarwinPlatform`. - /// - /// The environment is a variant of the platform like `device` or `simulator`. - /// Not all platforms support all values of environment. This type is a superset of - /// all the environments available on any case. - public enum Environment: Hashable { - case device - case simulator - case catalyst - - var withoutCatalyst: EnvironmentWithoutCatalyst? { - switch self { - case .device: - return .device - case .simulator: - return .simulator - case .catalyst: - return nil - } + /// macOS, corresponding to the `macosx`, `macos`, and `darwin` OS names. + case macOS + + /// iOS, corresponding to the `ios` and `iphoneos` OS names. This does not + /// match tvOS. + case iOS(Environment) + + /// tvOS, corresponding to the `tvos` OS name. + case tvOS(EnvironmentWithoutCatalyst) + + /// watchOS, corresponding to the `watchos` OS name. + case watchOS(EnvironmentWithoutCatalyst) + + /// The most general form of environment information attached to a + /// `DarwinPlatform`. + /// + /// The environment is a variant of the platform like `device` or `simulator`. + /// Not all platforms support all values of environment. This type is a superset of + /// all the environments available on any case. + public enum Environment: Hashable { + case device + case simulator + case catalyst + + var withoutCatalyst: EnvironmentWithoutCatalyst? { + switch self { + case .device: + return .device + case .simulator: + return .simulator + case .catalyst: + return nil + } + } + } + + public enum EnvironmentWithoutCatalyst: Hashable { + case device + case simulator } - } - - public enum EnvironmentWithoutCatalyst: Hashable { - case device - case simulator - } - - /// Returns the same platform, but with the environment replaced by - /// `environment`. Returns `nil` if `environment` is not valid - /// for `self`. - func with(_ environment: Environment) -> DarwinPlatform? { - switch self { - case .macOS: - guard environment == .device else { return nil } - return .macOS - case .iOS: - return .iOS(environment) - case .tvOS: - guard let withoutCatalyst = environment.withoutCatalyst else { return nil } - return .tvOS(withoutCatalyst) - case .watchOS: - guard let withoutCatalyst = environment.withoutCatalyst else { return nil } - return .watchOS(withoutCatalyst) + + /// Returns the same platform, but with the environment replaced by + /// `environment`. Returns `nil` if `environment` is not valid + /// for `self`. + func with(_ environment: Environment) -> DarwinPlatform? { + switch self { + case .macOS: + guard environment == .device else { return nil } + return .macOS + case .iOS: + return .iOS(environment) + case .tvOS: + guard let withoutCatalyst = environment.withoutCatalyst else { return nil } + return .tvOS(withoutCatalyst) + case .watchOS: + guard let withoutCatalyst = environment.withoutCatalyst else { return nil } + return .watchOS(withoutCatalyst) + } } - } - - public var platformDisplayName: String { - switch self { - case .macOS: - return "macOS" - case .iOS(.device): - return "iOS" - case .iOS(.simulator): - return "iOS Simulator" - case .iOS(.catalyst): - return "Mac Catalyst" - case .tvOS(.device): - return "tvOS" - case .tvOS(.simulator): - return "tvOS Simulator" - case .watchOS(.device): - return "watchOS" - case .watchOS(.simulator): - return "watchOS Simulator" + + public var platformDisplayName: String { + switch self { + case .macOS: + return "macOS" + case .iOS(.device): + return "iOS" + case .iOS(.simulator): + return "iOS Simulator" + case .iOS(.catalyst): + return "Mac Catalyst" + case .tvOS(.device): + return "tvOS" + case .tvOS(.simulator): + return "tvOS Simulator" + case .watchOS(.device): + return "watchOS" + case .watchOS(.simulator): + return "watchOS Simulator" + } } - } - - /// The platform name, i.e. the name clang uses to identify this platform in its - /// resource directory. - public var platformName: String { - switch self { - case .macOS: - return "macosx" - case .iOS(.device): - return "iphoneos" - case .iOS(.simulator): - return "iphonesimulator" - case .iOS(.catalyst): - return "maccatalyst" - case .tvOS(.device): - return "appletvos" - case .tvOS(.simulator): - return "appletvsimulator" - case .watchOS(.device): - return "watchos" - case .watchOS(.simulator): - return "watchsimulator" + + /// The platform name, i.e. the name clang uses to identify this platform in its + /// resource directory. + public var platformName: String { + switch self { + case .macOS: + return "macosx" + case .iOS(.device): + return "iphoneos" + case .iOS(.simulator): + return "iphonesimulator" + case .iOS(.catalyst): + return "maccatalyst" + case .tvOS(.device): + return "appletvos" + case .tvOS(.simulator): + return "appletvsimulator" + case .watchOS(.device): + return "watchos" + case .watchOS(.simulator): + return "watchsimulator" + } } - } - - /// The name the linker uses to identify this platform. - public var linkerPlatformName: String { - switch self { - case .macOS: - return "macos" - case .iOS(.device): - return "ios" - case .iOS(.simulator): - return "ios-simulator" - case .iOS(.catalyst): - return "mac-catalyst" - case .tvOS(.device): - return "tvos" - case .tvOS(.simulator): - return "tvos-simulator" - case .watchOS(.device): - return "watchos" - case .watchOS(.simulator): - return "watchos-simulator" + + /// The name the linker uses to identify this platform. + public var linkerPlatformName: String { + switch self { + case .macOS: + return "macos" + case .iOS(.device): + return "ios" + case .iOS(.simulator): + return "ios-simulator" + case .iOS(.catalyst): + return "mac-catalyst" + case .tvOS(.device): + return "tvos" + case .tvOS(.simulator): + return "tvos-simulator" + case .watchOS(.device): + return "watchos" + case .watchOS(.simulator): + return "watchos-simulator" + } } - } - - - /// The name used to identify this platform in compiler_rt file names. - public var libraryNameSuffix: String { - switch self { - case .macOS: - return "osx" - case .iOS(.device): - return "ios" - case .iOS(.simulator): - return "iossim" - case .iOS(.catalyst): - return "osx" - case .tvOS(.device): - return "tvos" - case .tvOS(.simulator): - return "tvossim" - case .watchOS(.device): - return "watchos" - case .watchOS(.simulator): - return "watchossim" + + /// The name used to identify this platform in compiler_rt file names. + public var libraryNameSuffix: String { + switch self { + case .macOS: + return "osx" + case .iOS(.device): + return "ios" + case .iOS(.simulator): + return "iossim" + case .iOS(.catalyst): + return "osx" + case .tvOS(.device): + return "tvos" + case .tvOS(.simulator): + return "tvossim" + case .watchOS(.device): + return "watchos" + case .watchOS(.simulator): + return "watchossim" + } } - } } extension Triple { - /// If this is a Darwin device platform, should it be inferred to be a device simulator? - public var _isSimulatorEnvironment: Bool { - return environment == .simulator - } - - /// Returns the OS version equivalent for the given platform, converting and - /// defaulting various representations. - /// - /// - Parameter compatibilityPlatform: Overrides the platform to be fetched. - /// For compatibility reasons, you sometimes have to e.g. pass an argument with a macOS - /// version number even when you're building watchOS code. This parameter specifies the - /// platform you need a version number for; the method will then return an arbitrary but - /// suitable version number for `compatibilityPlatform`. - /// - /// - Precondition: `self` must be able to provide a version for `compatibilityPlatform`. - /// Not all combinations are valid; in particular, you cannot fetch a watchOS version - /// from an iOS/tvOS triple or vice versa. - public func version(for compatibilityPlatform: DarwinPlatform? = nil) - -> Triple.Version - { - switch compatibilityPlatform ?? darwinPlatform! { - case .macOS: - return _macOSVersion ?? osVersion - case .iOS, .tvOS: - return _iOSVersion - case .watchOS: - return _watchOSVersion + /// If this is a Darwin device platform, should it be inferred to be a device simulator? + public var _isSimulatorEnvironment: Bool { + return environment == .simulator } - } - - /// Returns the `DarwinPlatform` for this triple, or `nil` if it is a non-Darwin - /// platform. - /// - /// - SeeAlso: DarwinPlatform - public var darwinPlatform: DarwinPlatform? { - func makeEnvironment() -> DarwinPlatform.EnvironmentWithoutCatalyst { - _isSimulatorEnvironment ? .simulator : .device + + /// Returns the OS version equivalent for the given platform, converting and + /// defaulting various representations. + /// + /// - Parameter compatibilityPlatform: Overrides the platform to be fetched. + /// For compatibility reasons, you sometimes have to e.g. pass an argument with a macOS + /// version number even when you're building watchOS code. This parameter specifies the + /// platform you need a version number for; the method will then return an arbitrary but + /// suitable version number for `compatibilityPlatform`. + /// + /// - Precondition: `self` must be able to provide a version for `compatibilityPlatform`. + /// Not all combinations are valid; in particular, you cannot fetch a watchOS version + /// from an iOS/tvOS triple or vice versa. + public func version(for compatibilityPlatform: DarwinPlatform? = nil) + -> Triple.Version + { + switch compatibilityPlatform ?? darwinPlatform! { + case .macOS: + return _macOSVersion ?? osVersion + case .iOS, .tvOS: + return _iOSVersion + case .watchOS: + return _watchOSVersion + } } - switch os { - case .darwin, .macosx: - return .macOS - case .ios: - if isMacCatalyst { - return .iOS(.catalyst) - } else if _isSimulatorEnvironment { - return .iOS(.simulator) - } else { - return .iOS(.device) - } - case .watchos: - return .watchOS(makeEnvironment()) - case .tvos: - return .tvOS(makeEnvironment()) - default: - return nil + + /// Returns the `DarwinPlatform` for this triple, or `nil` if it is a non-Darwin + /// platform. + /// + /// - SeeAlso: DarwinPlatform + public var darwinPlatform: DarwinPlatform? { + func makeEnvironment() -> DarwinPlatform.EnvironmentWithoutCatalyst { + _isSimulatorEnvironment ? .simulator : .device + } + switch os { + case .darwin, .macosx: + return .macOS + case .ios: + if isMacCatalyst { + return .iOS(.catalyst) + } else if _isSimulatorEnvironment { + return .iOS(.simulator) + } else { + return .iOS(.device) + } + case .watchos: + return .watchOS(makeEnvironment()) + case .tvos: + return .tvOS(makeEnvironment()) + default: + return nil + } } - } - - // The Darwin platform version used for linking. - public var darwinLinkerPlatformVersion: Version { - precondition(self.os?.isDarwin ?? false) - switch darwinPlatform! { - case .macOS: - // The integrated driver falls back to `osVersion` for invalid macOS - // versions, this decision might be worth revisiting. - let macVersion = _macOSVersion ?? osVersion - // The first deployment of arm64 for macOS is version 11 - if macVersion.major < 11 && arch == .aarch64 { - return Version(11, 0, 0) - } - - return macVersion - case .iOS(.catalyst): - // Mac Catalyst on arm was introduced with an iOS deployment target of - // 14.0; the linker doesn't want to see a deployment target before that. - if _iOSVersion.major < 14 && arch == .aarch64 { - return Version(14, 0, 0) - } - - // Mac Catalyst was introduced with an iOS deployment target of 13.1; - // the linker doesn't want to see a deployment target before that. - if _iOSVersion.major < 13 { - return Version(13, 1, 0) - } - - return _iOSVersion - case .iOS(.device), .iOS(.simulator), .tvOS(_): - // The first deployment of arm64 simulators is iOS/tvOS 14.0; - // the linker doesn't want to see a deployment target before that. - if _isSimulatorEnvironment && _iOSVersion.major < 14 && arch == .aarch64 { - return Version(14, 0, 0) - } - - return _iOSVersion - case .watchOS(_): - // The first deployment of arm64 simulators is watchOS 7; - // the linker doesn't want to see a deployment target before that. - if _isSimulatorEnvironment && osVersion.major < 7 && arch == .aarch64 { - return Version(7, 0, 0) - } - - return osVersion + + // The Darwin platform version used for linking. + public var darwinLinkerPlatformVersion: Version { + precondition(self.os?.isDarwin ?? false) + switch darwinPlatform! { + case .macOS: + // The integrated driver falls back to `osVersion` for invalid macOS + // versions, this decision might be worth revisiting. + let macVersion = _macOSVersion ?? osVersion + // The first deployment of arm64 for macOS is version 11 + if macVersion.major < 11 && arch == .aarch64 { + return Version(11, 0, 0) + } + + return macVersion + case .iOS(.catalyst): + // Mac Catalyst on arm was introduced with an iOS deployment target of + // 14.0; the linker doesn't want to see a deployment target before that. + if _iOSVersion.major < 14 && arch == .aarch64 { + return Version(14, 0, 0) + } + + // Mac Catalyst was introduced with an iOS deployment target of 13.1; + // the linker doesn't want to see a deployment target before that. + if _iOSVersion.major < 13 { + return Version(13, 1, 0) + } + + return _iOSVersion + case .iOS(.device), .iOS(.simulator), .tvOS(_): + // The first deployment of arm64 simulators is iOS/tvOS 14.0; + // the linker doesn't want to see a deployment target before that. + if _isSimulatorEnvironment && _iOSVersion.major < 14 && arch == .aarch64 { + return Version(14, 0, 0) + } + + return _iOSVersion + case .watchOS(_): + // The first deployment of arm64 simulators is watchOS 7; + // the linker doesn't want to see a deployment target before that. + if _isSimulatorEnvironment && osVersion.major < 7 && arch == .aarch64 { + return Version(7, 0, 0) + } + + return osVersion + } } - } - - /// The platform name, i.e. the name clang uses to identify this target in its - /// resource directory. - /// - /// - Parameter conflatingDarwin: If true, all Darwin platforms will be - /// identified as just `darwin` instead of by individual platform names. - /// Defaults to `false`. - public func platformName(conflatingDarwin: Bool = false) -> String? { - switch os { - case nil: - fatalError("unknown OS") - case .darwin, .macosx, .ios, .tvos, .watchos: - guard let darwinPlatform = darwinPlatform else { - fatalError("unsupported darwin platform kind?") - } - return conflatingDarwin ? "darwin" : darwinPlatform.platformName - - case .linux: - return environment == .android ? "android" : "linux" - case .freebsd: - return "freebsd" - case .openbsd: - return "openbsd" - case .win32: - switch environment { - case .cygnus: - return "cygwin" - case .gnu: - return "mingw" - case .msvc, .itanium: - return "windows" - default: - if let environment = environment { - fatalError("unsupported Windows environment: \(environment)") - } else { - fatalError("unsupported Windows environment: nil") + + /// The platform name, i.e. the name clang uses to identify this target in its + /// resource directory. + /// + /// - Parameter conflatingDarwin: If true, all Darwin platforms will be + /// identified as just `darwin` instead of by individual platform names. + /// Defaults to `false`. + public func platformName(conflatingDarwin: Bool = false) -> String? { + switch os { + case nil: + fatalError("unknown OS") + case .darwin, .macosx, .ios, .tvos, .watchos: + guard let darwinPlatform = darwinPlatform else { + fatalError("unsupported darwin platform kind?") + } + return conflatingDarwin ? "darwin" : darwinPlatform.platformName + + case .linux: + return environment == .android ? "android" : "linux" + case .freebsd: + return "freebsd" + case .openbsd: + return "openbsd" + case .win32: + switch environment { + case .cygnus: + return "cygwin" + case .gnu: + return "mingw" + case .msvc, .itanium: + return "windows" + default: + if let environment = environment { + fatalError("unsupported Windows environment: \(environment)") + } else { + fatalError("unsupported Windows environment: nil") + } + } + case .ps4: + return "ps4" + case .haiku: + return "haiku" + case .wasi: + return "wasi" + case .noneOS: + return nil + + // Explicitly spell out the remaining cases to force a compile error when + // Triple updates + case .ananas, .cloudABI, .dragonFly, .fuchsia, .kfreebsd, .lv2, .netbsd, + .solaris, .minix, .rtems, .nacl, .cnk, .aix, .cuda, .nvcl, .amdhsa, + .elfiamcu, .mesa3d, .contiki, .amdpal, .hermitcore, .hurd, .emscripten: + return nil } - } - case .ps4: - return "ps4" - case .haiku: - return "haiku" - case .wasi: - return "wasi" - case .noneOS: - return nil - - // Explicitly spell out the remaining cases to force a compile error when - // Triple updates - case .ananas, .cloudABI, .dragonFly, .fuchsia, .kfreebsd, .lv2, .netbsd, - .solaris, .minix, .rtems, .nacl, .cnk, .aix, .cuda, .nvcl, .amdhsa, - .elfiamcu, .mesa3d, .contiki, .amdpal, .hermitcore, .hurd, .emscripten: - return nil } - } } extension Triple { - /// Represents the availability of a feature that is supported on some platforms - /// and versions, but not all. For Darwin versions, the version numbers provided - /// should be the version where the feature was added or the change was - /// introduced, because all version checks are in the form of - /// `tripleVersion >= featureVersion`. - /// - /// - SeeAlso: `Triple.supports(_:)` -public struct FeatureAvailability: Sendable { - - public enum Availability: Sendable { - case unavailable - case available(since: Version) - case availableInAllVersions - } - - public let macOS: Availability - public let iOS: Availability - public let tvOS: Availability - public let watchOS: Availability - - // TODO: We should have linux, windows, etc. - public let nonDarwin: Bool - - /// Describes the availability of a feature that is supported on multiple platforms, - /// but is tied to a particular version. - public init( - macOS: Availability, - iOS: Availability, - tvOS: Availability, - watchOS: Availability, - nonDarwin: Bool = false - ) { - self.macOS = macOS - self.iOS = iOS - self.tvOS = tvOS - self.watchOS = watchOS - self.nonDarwin = nonDarwin - } + /// Represents the availability of a feature that is supported on some platforms + /// and versions, but not all. For Darwin versions, the version numbers provided + /// should be the version where the feature was added or the change was + /// introduced, because all version checks are in the form of + /// `tripleVersion >= featureVersion`. + /// + /// - SeeAlso: `Triple.supports(_:)` + public struct FeatureAvailability: Sendable { + + public enum Availability: Sendable { + case unavailable + case available(since: Version) + case availableInAllVersions + } - /// Returns the version when the feature was introduced on the specified Darwin - /// platform, or `.unavailable` if the feature has not been introduced there. - public subscript(darwinPlatform: DarwinPlatform) -> Availability { - switch darwinPlatform { - case .macOS: - return macOS - case .iOS: - return iOS - case .tvOS: - return tvOS - case .watchOS: - return watchOS - } - } - } + public let macOS: Availability + public let iOS: Availability + public let tvOS: Availability + public let watchOS: Availability + + // TODO: We should have linux, windows, etc. + public let nonDarwin: Bool + + /// Describes the availability of a feature that is supported on multiple platforms, + /// but is tied to a particular version. + public init( + macOS: Availability, + iOS: Availability, + tvOS: Availability, + watchOS: Availability, + nonDarwin: Bool = false + ) { + self.macOS = macOS + self.iOS = iOS + self.tvOS = tvOS + self.watchOS = watchOS + self.nonDarwin = nonDarwin + } - /// Checks whether the triple supports the specified feature, i.e., the feature - /// has been introduced by the OS and version indicated by the triple. - public func supports(_ feature: FeatureAvailability) -> Bool { - guard let darwinPlatform = darwinPlatform else { - return feature.nonDarwin + /// Returns the version when the feature was introduced on the specified Darwin + /// platform, or `.unavailable` if the feature has not been introduced there. + public subscript(darwinPlatform: DarwinPlatform) -> Availability { + switch darwinPlatform { + case .macOS: + return macOS + case .iOS: + return iOS + case .tvOS: + return tvOS + case .watchOS: + return watchOS + } + } } - - switch feature[darwinPlatform] { - case .unavailable: - return false - case .available(let introducedVersion): - return version(for: darwinPlatform) >= introducedVersion - case .availableInAllVersions: - return true + + /// Checks whether the triple supports the specified feature, i.e., the feature + /// has been introduced by the OS and version indicated by the triple. + public func supports(_ feature: FeatureAvailability) -> Bool { + guard let darwinPlatform = darwinPlatform else { + return feature.nonDarwin + } + + switch feature[darwinPlatform] { + case .unavailable: + return false + case .available(let introducedVersion): + return version(for: darwinPlatform) >= introducedVersion + case .availableInAllVersions: + return true + } } - } } extension Triple.FeatureAvailability { - /// Linking `libarclite` is unnecessary for triples supporting this feature. - /// - /// This impacts the `-link-objc-runtime` flag in Swift, which is akin to the - /// `-fobjc-link-runtime` build setting in clang. When set, these flags - /// automatically link libobjc, and any compatibility libraries that don't - /// ship with the OS. The versions here are the first OSes that support - /// ARC natively in their respective copies of the Objective-C runtime, - /// and therefore do not require additional support libraries. - static let nativeARC = Self( - macOS: .available(since: Triple.Version(10, 11, 0)), - iOS: .available(since: Triple.Version(9, 0, 0)), - tvOS: .available(since: Triple.Version(9, 0, 0)), - watchOS: .availableInAllVersions - ) - // When updating the versions listed here, please record the most recent - // feature being depended on and when it was introduced: - // - // - Make assigning 'nil' to an NSMutableDictionary subscript delete the - // entry, like it does for Swift.Dictionary, rather than trap. + /// Linking `libarclite` is unnecessary for triples supporting this feature. + /// + /// This impacts the `-link-objc-runtime` flag in Swift, which is akin to the + /// `-fobjc-link-runtime` build setting in clang. When set, these flags + /// automatically link libobjc, and any compatibility libraries that don't + /// ship with the OS. The versions here are the first OSes that support + /// ARC natively in their respective copies of the Objective-C runtime, + /// and therefore do not require additional support libraries. + static let nativeARC = Self( + macOS: .available(since: Triple.Version(10, 11, 0)), + iOS: .available(since: Triple.Version(9, 0, 0)), + tvOS: .available(since: Triple.Version(9, 0, 0)), + watchOS: .availableInAllVersions + ) + // When updating the versions listed here, please record the most recent + // feature being depended on and when it was introduced: + // + // - Make assigning 'nil' to an NSMutableDictionary subscript delete the + // entry, like it does for Swift.Dictionary, rather than trap. } diff --git a/Sources/Basics/Vendor/Triple.swift b/Sources/Basics/Vendor/Triple.swift index 441962f43ea..8bfb1915f24 100644 --- a/Sources/Basics/Vendor/Triple.swift +++ b/Sources/Basics/Vendor/Triple.swift @@ -44,193 +44,196 @@ /// This is a port of https://github.com/apple/swift-llvm/blob/stable/include/llvm/ADT/Triple.h @dynamicMemberLookup public struct Triple: Sendable { - /// `Triple` proxies predicates from `Triple.OS`, returning `false` for an unknown OS. - public subscript(dynamicMember predicate: KeyPath) -> Bool { - os?[keyPath: predicate] ?? false - } + /// `Triple` proxies predicates from `Triple.OS`, returning `false` for an unknown OS. + public subscript(dynamicMember predicate: KeyPath) -> Bool { + os?[keyPath: predicate] ?? false + } - /// The original triple string. - public let triple: String + /// The original triple string. + public let triple: String - /// The parsed arch. - public let arch: Arch? + /// The parsed arch. + public let arch: Arch? - /// The parsed subarchitecture. - public let subArch: SubArch? + /// The parsed subarchitecture. + public let subArch: SubArch? - /// The parsed vendor. - public let vendor: Vendor? + /// The parsed vendor. + public let vendor: Vendor? - /// The parsed OS. - public let os: OS? + /// The parsed OS. + public let os: OS? - /// The parsed Environment type. - public let environment: Environment? + /// The parsed Environment type. + public let environment: Environment? - /// The object format type. - public let objectFormat: ObjectFormat? + /// The object format type. + public let objectFormat: ObjectFormat? - /// Represents a version that may be present in the target triple. + /// Represents a version that may be present in the target triple. public struct Version: Equatable, Comparable, CustomStringConvertible, Sendable { - public static let zero = Version(0, 0, 0) - - public var major: Int - public var minor: Int - public var micro: Int - - public init(parse string: S) { - let components = string.split(separator: ".", maxSplits: 3).map{ Int($0) ?? 0 } - self.major = components.count > 0 ? components[0] : 0 - self.minor = components.count > 1 ? components[1] : 0 - self.micro = components.count > 2 ? components[2] : 0 - } + public static let zero = Version(0, 0, 0) - public init(_ major: Int, _ minor: Int, _ micro: Int) { - self.major = major - self.minor = minor - self.micro = micro - } + public var major: Int + public var minor: Int + public var micro: Int - public static func <(lhs: Version, rhs: Version) -> Bool { - return (lhs.major, lhs.minor, lhs.micro) < (rhs.major, rhs.minor, rhs.micro) - } + public init(parse string: S) { + let components = string.split(separator: ".", maxSplits: 3).map { Int($0) ?? 0 } + self.major = components.count > 0 ? components[0] : 0 + self.minor = components.count > 1 ? components[1] : 0 + self.micro = components.count > 2 ? components[2] : 0 + } - public var description: String { - return "\(major).\(minor).\(micro)" - } - } - - public init(_ string: String, normalizing: Bool = false) { - var parser = TripleParser(string, allowMore: normalizing) - - // First, see if each component parses at its expected position. - var parsedArch = parser.match(ArchInfo.self, at: 0) - var parsedVendor = parser.match(Vendor.self, at: 1) - var parsedOS = parser.match(OS.self, at: 2) - var parsedEnv = parser.match(EnvInfo.self, at: 3) - - if normalizing { - // Next, try to fill in each unmatched field from the rejected components. - parser.rematch(&parsedArch, at: 0) - parser.rematch(&parsedVendor, at: 1) - parser.rematch(&parsedOS, at: 2) - parser.rematch(&parsedEnv, at: 3) - - let isCygwin = parser.componentsIndicateCygwin - let isMinGW32 = parser.componentsIndicateMinGW32 - - if - let parsedEnv = parsedEnv, - parsedEnv.value.environment == .android, - parsedEnv.substring.hasPrefix("androideabi") { - let androidVersion = parsedEnv.substring.dropFirst("androideabi".count) - - parser.components[3] = "android\(androidVersion)" - } - - // SUSE uses "gnueabi" to mean "gnueabihf" - if parsedVendor?.value == .suse && parsedEnv?.value.environment == .gnueabi { - parser.components[3] = "gnueabihf" - } - - if parsedOS?.value == .win32 { - parser.components.resize(toCount: 4, paddingWith: "") - parser.components[2] = "windows" - if parsedEnv?.value.environment == nil { - if let objectFormat = parsedEnv?.value.objectFormat, objectFormat != .coff { - parser.components[3] = Substring(objectFormat.name) - } else { - parser.components[3] = "msvc" - } + public init(_ major: Int, _ minor: Int, _ micro: Int) { + self.major = major + self.minor = minor + self.micro = micro } - } else if isMinGW32 { - parser.components.resize(toCount: 4, paddingWith: "") - parser.components[2] = "windows" - parser.components[3] = "gnu" - } else if isCygwin { - parser.components.resize(toCount: 4, paddingWith: "") - parser.components[2] = "windows" - parser.components[3] = "cygnus" - } - - if isMinGW32 || isCygwin || (parsedOS?.value == .win32 && parsedEnv?.value.environment != nil) { - if let objectFormat = parsedEnv?.value.objectFormat, objectFormat != .coff { - parser.components.resize(toCount: 5, paddingWith: "") - parser.components[4] = Substring(objectFormat.name) + + public static func < (lhs: Version, rhs: Version) -> Bool { + return (lhs.major, lhs.minor, lhs.micro) < (rhs.major, rhs.minor, rhs.micro) } - } - // Now that we've parsed everything, we construct a normalized form of the - // triple string. - triple = parser.components.map({ $0.isEmpty ? "unknown" : $0 }).joined(separator: "-") - } - else { - triple = string + public var description: String { + return "\(major).\(minor).\(micro)" + } } - // Unpack the parsed data into the fields. If no environment info was found, - // attempt to infer it from other fields. - self.arch = parsedArch?.value.arch - self.subArch = parsedArch?.value.subArch - self.vendor = parsedVendor?.value - self.os = parsedOS?.value - - if let parsedEnv = parsedEnv { - self.environment = parsedEnv.value.environment - self.objectFormat = parsedEnv.value.objectFormat - ?? ObjectFormat.infer(arch: parsedArch?.value.arch, - os: parsedOS?.value) - } - else { - self.environment = Environment.infer(archName: parsedArch?.substring) - self.objectFormat = ObjectFormat.infer(arch: parsedArch?.value.arch, - os: parsedOS?.value) + public init(_ string: String, normalizing: Bool = false) { + var parser = TripleParser(string, allowMore: normalizing) + + // First, see if each component parses at its expected position. + var parsedArch = parser.match(ArchInfo.self, at: 0) + var parsedVendor = parser.match(Vendor.self, at: 1) + var parsedOS = parser.match(OS.self, at: 2) + var parsedEnv = parser.match(EnvInfo.self, at: 3) + + if normalizing { + // Next, try to fill in each unmatched field from the rejected components. + parser.rematch(&parsedArch, at: 0) + parser.rematch(&parsedVendor, at: 1) + parser.rematch(&parsedOS, at: 2) + parser.rematch(&parsedEnv, at: 3) + + let isCygwin = parser.componentsIndicateCygwin + let isMinGW32 = parser.componentsIndicateMinGW32 + + if let parsedEnv = parsedEnv, + parsedEnv.value.environment == .android, + parsedEnv.substring.hasPrefix("androideabi") + { + let androidVersion = parsedEnv.substring.dropFirst("androideabi".count) + + parser.components[3] = "android\(androidVersion)" + } + + // SUSE uses "gnueabi" to mean "gnueabihf" + if parsedVendor?.value == .suse && parsedEnv?.value.environment == .gnueabi { + parser.components[3] = "gnueabihf" + } + + if parsedOS?.value == .win32 { + parser.components.resize(toCount: 4, paddingWith: "") + parser.components[2] = "windows" + if parsedEnv?.value.environment == nil { + if let objectFormat = parsedEnv?.value.objectFormat, objectFormat != .coff { + parser.components[3] = Substring(objectFormat.name) + } else { + parser.components[3] = "msvc" + } + } + } else if isMinGW32 { + parser.components.resize(toCount: 4, paddingWith: "") + parser.components[2] = "windows" + parser.components[3] = "gnu" + } else if isCygwin { + parser.components.resize(toCount: 4, paddingWith: "") + parser.components[2] = "windows" + parser.components[3] = "cygnus" + } + + if isMinGW32 || isCygwin || (parsedOS?.value == .win32 && parsedEnv?.value.environment != nil) { + if let objectFormat = parsedEnv?.value.objectFormat, objectFormat != .coff { + parser.components.resize(toCount: 5, paddingWith: "") + parser.components[4] = Substring(objectFormat.name) + } + } + + // Now that we've parsed everything, we construct a normalized form of the + // triple string. + triple = parser.components.map({ $0.isEmpty ? "unknown" : $0 }).joined(separator: "-") + } else { + triple = string + } + + // Unpack the parsed data into the fields. If no environment info was found, + // attempt to infer it from other fields. + self.arch = parsedArch?.value.arch + self.subArch = parsedArch?.value.subArch + self.vendor = parsedVendor?.value + self.os = parsedOS?.value + + if let parsedEnv = parsedEnv { + self.environment = parsedEnv.value.environment + self.objectFormat = + parsedEnv.value.objectFormat + ?? ObjectFormat.infer( + arch: parsedArch?.value.arch, + os: parsedOS?.value + ) + } else { + self.environment = Environment.infer(archName: parsedArch?.substring) + self.objectFormat = ObjectFormat.infer( + arch: parsedArch?.value.arch, + os: parsedOS?.value + ) + } } - } } extension Triple: Codable { - public init(from decoder: Decoder) throws { - self.init(try decoder.singleValueContainer().decode(String.self), normalizing: false) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(triple) - } + public init(from decoder: Decoder) throws { + self.init(try decoder.singleValueContainer().decode(String.self), normalizing: false) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(triple) + } } // MARK: - Triple component parsing fileprivate protocol TripleComponent { - static func parse(_ component: Substring) -> Self? + static func parse(_ component: Substring) -> Self? - static func valueIsValid(_ value: Substring) -> Bool + static func valueIsValid(_ value: Substring) -> Bool } extension TripleComponent { - static func valueIsValid(_ value: Substring) -> Bool { - parse(value) != nil - } + static func valueIsValid(_ value: Substring) -> Bool { + parse(value) != nil + } } fileprivate struct ParsedComponent { - let value: Value - let substring: Substring - - /// Attempts to parse `component` with `parser`, placing it in `rejects` if - /// it does not succeed. - /// - /// - Returns: `nil` if `type` cannot parse `component`; otherwise, an - /// instance containing the component and its parsed value. - init?(_ component: Substring, as type: Value.Type) { - guard let value = type.parse(component) else { - return nil - } + let value: Value + let substring: Substring + + /// Attempts to parse `component` with `parser`, placing it in `rejects` if + /// it does not succeed. + /// + /// - Returns: `nil` if `type` cannot parse `component`; otherwise, an + /// instance containing the component and its parsed value. + init?(_ component: Substring, as type: Value.Type) { + guard let value = type.parse(component) else { + return nil + } - self.value = value - self.substring = component - } + self.value = value + self.substring = component + } } /// Holds the list of components in this string, as well as whether or not we @@ -246,599 +249,606 @@ fileprivate struct ParsedComponent { /// /// In non-normalizing mode, we simply skip the second step. fileprivate struct TripleParser { - var components: [Substring] - var isMatched: Set = [] - - var componentsIndicateCygwin: Bool { - components.count > 2 ? components[2].hasPrefix("cygwin") : false - } - - var componentsIndicateMinGW32: Bool { - components.count > 2 ? components[2].hasPrefix("mingw") : false - } - - init(_ string: String, allowMore: Bool) { - components = string.split( - separator: "-", maxSplits: allowMore ? Int.max : 3, - omittingEmptySubsequences: false - ) - } - - /// Attempt to parse the component at position `i` as a `Value`, marking it as - /// matched if successful. - mutating func match(_: Value.Type, at i: Int) - -> ParsedComponent? - { - guard - i < components.endIndex, - let parsed = ParsedComponent(components[i], as: Value.self) - else { - return nil - } - - precondition(!isMatched.contains(i)) - isMatched.insert(i) + var components: [Substring] + var isMatched: Set = [] - return parsed - } + var componentsIndicateCygwin: Bool { + components.count > 2 ? components[2].hasPrefix("cygwin") : false + } - /// If `value` has not been filled in, attempt to parse all unmatched - /// components with it, correcting the components list if a match is found. - mutating func rematch( - _ value: inout ParsedComponent?, at correctIndex: Int - ) { - guard value == nil else { return } + var componentsIndicateMinGW32: Bool { + components.count > 2 ? components[2].hasPrefix("mingw") : false + } - precondition(!isMatched.contains(correctIndex), - "Lost the parsed component somehow?") + init(_ string: String, allowMore: Bool) { + components = string.split( + separator: "-", + maxSplits: allowMore ? Int.max : 3, + omittingEmptySubsequences: false + ) + } - for i in unmatchedIndices { - guard Value.valueIsValid(components[i]) else { - continue - } + /// Attempt to parse the component at position `i` as a `Value`, marking it as + /// matched if successful. + mutating func match(_: Value.Type, at i: Int) + -> ParsedComponent? + { + guard + i < components.endIndex, + let parsed = ParsedComponent(components[i], as: Value.self) + else { + return nil + } - value = ParsedComponent(components[i], as: Value.self) - shiftComponent(at: i, to: correctIndex) - isMatched.insert(correctIndex) + precondition(!isMatched.contains(i)) + isMatched.insert(i) - return + return parsed } - } - /// Returns `component.indices` with matched elements lazily filtered out. - private var unmatchedIndices: LazyFilterSequence> { - components.indices.lazy.filter { [isMatched] in - !isMatched.contains($0) - } - } - - /// Rearrange `components` so that the element at `actualIndex` now appears - /// at `correctIndex`, without moving any components that have already - /// matched. - /// - /// The exact transformations performed by this function are difficult to - /// describe concisely, but they work well in practice for the ways people - /// tend to permute triples. Essentially: - /// - /// * If a component appears later than it ought to, it is moved to the right - /// location and other unmatched components are shifted later. - /// * If a component appears earlier than it ought to, empty components are - /// either found later in the list and moved before it, or created from - /// whole cloth and inserted before it. - /// * If no movement is necessary, this is a no-op. - /// - /// - Parameter actualIndex: The index that the component is currently at. - /// - Parameter correctIndex: The index that the component ought to be at. - /// - /// - Precondition: Neither `correctIndex` nor `actualIndex` are matched. - private mutating func shiftComponent( - at actualIndex: Int, - to correctIndex: Int - ) { - // Don't mark actualIndex as matched until after you've called this method. - precondition(!isMatched.contains(actualIndex), - "actualIndex was already matched to something else?") - precondition(!isMatched.contains(correctIndex), - "correctIndex already had something match it?") - - if correctIndex < actualIndex { - // Repeatedly swap `actualIndex` with its leftward neighbor, skipping - // matched components, until it finds its way to `correctIndex`. - - // Compute all of the indices that we'll shift, not including any that - // have matched, and then build a reversed list of adjacent pairs. (That - // is, if the filter returns `[1,2,4]`, the resulting list will be - // `[(4,2),(2,1)]`.) - let swaps = unmatchedIndices[correctIndex...actualIndex] - .zippedPairs().reversed() - - // Swap each pair. This has the effect of moving `actualIndex` to - // `correctIndex` and shifting each unmatched element between them to - // take up the space. Swapping instead of assigning ought to avoid retain - // count traffic. - for (earlier, later) in swaps { - components.swapAt(earlier, later) - } + /// If `value` has not been filled in, attempt to parse all unmatched + /// components with it, correcting the components list if a match is found. + mutating func rematch( + _ value: inout ParsedComponent?, + at correctIndex: Int + ) { + guard value == nil else { return } + + precondition( + !isMatched.contains(correctIndex), + "Lost the parsed component somehow?" + ) + + for i in unmatchedIndices { + guard Value.valueIsValid(components[i]) else { + continue + } + + value = ParsedComponent(components[i], as: Value.self) + shiftComponent(at: i, to: correctIndex) + isMatched.insert(correctIndex) + + return + } } - // The rest of this method is concerned with shifting components rightward. - // If we don't need to do that, we're done. - guard correctIndex > actualIndex else { return } - - // We will essentially insert one empty component in front of `actualIndex`, - // then recurse to shift `actualIndex + 1` if necessary. However, we want to - // avoid shifting matched components and eat empty components, so this is - // all a bit more complicated than just that. - - // Create a new empty component. We call it `removed` because for most - // of this variable's lifetime, `removed` is a component that has been - // removed from the list. - var removed: Substring = "" - - // This loop has the effect of inserting the empty component and - // shifting other unmatched components rightward until we either remove - // an empty unmatched component, or remove the last element of the list. - for i in unmatchedIndices[actualIndex...] { - swap(&removed, &components[i]) - - // If the element we removed is empty, consume it rather than reinserting - // it later in the list. - if removed.isEmpty { break } + /// Returns `component.indices` with matched elements lazily filtered out. + private var unmatchedIndices: LazyFilterSequence> { + components.indices.lazy.filter { [isMatched] in + !isMatched.contains($0) + } } - // If we shifted a non-empty component off the end, add it back in. - if !removed.isEmpty { - components.append(removed) - } + /// Rearrange `components` so that the element at `actualIndex` now appears + /// at `correctIndex`, without moving any components that have already + /// matched. + /// + /// The exact transformations performed by this function are difficult to + /// describe concisely, but they work well in practice for the ways people + /// tend to permute triples. Essentially: + /// + /// * If a component appears later than it ought to, it is moved to the right + /// location and other unmatched components are shifted later. + /// * If a component appears earlier than it ought to, empty components are + /// either found later in the list and moved before it, or created from + /// whole cloth and inserted before it. + /// * If no movement is necessary, this is a no-op. + /// + /// - Parameter actualIndex: The index that the component is currently at. + /// - Parameter correctIndex: The index that the component ought to be at. + /// + /// - Precondition: Neither `correctIndex` nor `actualIndex` are matched. + private mutating func shiftComponent( + at actualIndex: Int, + to correctIndex: Int + ) { + // Don't mark actualIndex as matched until after you've called this method. + precondition( + !isMatched.contains(actualIndex), + "actualIndex was already matched to something else?" + ) + precondition( + !isMatched.contains(correctIndex), + "correctIndex already had something match it?" + ) + + if correctIndex < actualIndex { + // Repeatedly swap `actualIndex` with its leftward neighbor, skipping + // matched components, until it finds its way to `correctIndex`. + + // Compute all of the indices that we'll shift, not including any that + // have matched, and then build a reversed list of adjacent pairs. (That + // is, if the filter returns `[1,2,4]`, the resulting list will be + // `[(4,2),(2,1)]`.) + let swaps = unmatchedIndices[correctIndex...actualIndex] + .zippedPairs().reversed() + + // Swap each pair. This has the effect of moving `actualIndex` to + // `correctIndex` and shifting each unmatched element between them to + // take up the space. Swapping instead of assigning ought to avoid retain + // count traffic. + for (earlier, later) in swaps { + components.swapAt(earlier, later) + } + } + + // The rest of this method is concerned with shifting components rightward. + // If we don't need to do that, we're done. + guard correctIndex > actualIndex else { return } + + // We will essentially insert one empty component in front of `actualIndex`, + // then recurse to shift `actualIndex + 1` if necessary. However, we want to + // avoid shifting matched components and eat empty components, so this is + // all a bit more complicated than just that. + + // Create a new empty component. We call it `removed` because for most + // of this variable's lifetime, `removed` is a component that has been + // removed from the list. + var removed: Substring = "" + + // This loop has the effect of inserting the empty component and + // shifting other unmatched components rightward until we either remove + // an empty unmatched component, or remove the last element of the list. + for i in unmatchedIndices[actualIndex...] { + swap(&removed, &components[i]) + + // If the element we removed is empty, consume it rather than reinserting + // it later in the list. + if removed.isEmpty { break } + } + + // If we shifted a non-empty component off the end, add it back in. + if !removed.isEmpty { + components.append(removed) + } - // Find the next unmatched index after `actualIndex`; that's where we moved - // the element at `actualIndex` to. - let nextIndex = unmatchedIndices[(actualIndex + 1).. Zip2Sequence { - zip(dropLast(), dropFirst()) - } + fileprivate func zippedPairs() -> Zip2Sequence { + zip(dropLast(), dropFirst()) + } } // MARK: - Parse Arch extension Triple { - fileprivate struct ArchInfo: TripleComponent { - var arch: Triple.Arch - var subArch: Triple.SubArch? - - fileprivate static func parse(_ component: Substring) -> ArchInfo? { - // This code assumes that all architectures with a subarch also have an arch. - // This is slightly different from llvm::Triple, whose - // startswith/endswith-based logic might occasionally recognize a subarch - // without an arch, e.g. "xxkalimba5" would have an unknown arch and a - // kalimbav5 subarch. I'm pretty sure that's undesired behavior from LLVM. - - guard let arch = Triple.Arch.parse(component) else { return nil } - return ArchInfo(arch: arch, subArch: Triple.SubArch.parse(component)) - } - } - -public enum Arch: String, CaseIterable, Decodable, Sendable { - /// ARM (little endian): arm, armv.*, xscale - case arm - // ARM (big endian): armeb - case armeb - /// AArch64 (little endian): aarch64 - case aarch64 - /// AArch64e (little endian): aarch64e - case aarch64e - /// AArch64 (big endian): aarch64_be - case aarch64_be - // AArch64 (little endian) ILP32: aarch64_32 - case aarch64_32 - /// ARC: Synopsis ARC - case arc - /// AVR: Atmel AVR microcontroller - case avr - /// eBPF or extended BPF or 64-bit BPF (little endian) - case bpfel - /// eBPF or extended BPF or 64-bit BPF (big endian) - case bpfeb - /// Hexagon: hexagon - case hexagon - /// MIPS: mips, mipsallegrex, mipsr6 - case mips - /// MIPSEL: mipsel, mipsallegrexe, mipsr6el - case mipsel - // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6 - case mips64 - // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el - case mips64el - // MSP430: msp430 - case msp430 - // PPC: powerpc - case ppc - // PPC64: powerpc64, ppu - case ppc64 - // PPC64LE: powerpc64le - case ppc64le - // R600: AMD GPUs HD2XXX - HD6XXX - case r600 - // AMDGCN: AMD GCN GPUs - case amdgcn - // RISC-V (32-bit): riscv32 - case riscv32 - // RISC-V (64-bit): riscv64 - case riscv64 - // Sparc: sparc - case sparc - // Sparcv9: Sparcv9 - case sparcv9 - // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant - case sparcel - // SystemZ: s390x - case systemz - // TCE (http://tce.cs.tut.fi/): tce - case tce - // TCE little endian (http://tce.cs.tut.fi/): tcele - case tcele - // Thumb (little endian): thumb, thumbv.* - case thumb - // Thumb (big endian): thumbeb - case thumbeb - // X86: i[3-9]86 - case x86 = "i386" - // X86-64: amd64, x86_64 - case x86_64 - // XCore: xcore - case xcore - // NVPTX: 32-bit - case nvptx - // NVPTX: 64-bit - case nvptx64 - // le32: generic little-endian 32-bit CPU (PNaCl) - case le32 - // le64: generic little-endian 64-bit CPU (PNaCl) - case le64 - // AMDIL - case amdil - // AMDIL with 64-bit pointers - case amdil64 - // AMD HSAIL - case hsail - // AMD HSAIL with 64-bit pointers - case hsail64 - // SPIR: standard portable IR for OpenCL 32-bit version - case spir - // SPIR: standard portable IR for OpenCL 64-bit version - case spir64 - // Kalimba: generic kalimba - case kalimba - // SHAVE: Movidius vector VLIW processors - case shave - // Lanai: Lanai 32-bit - case lanai - // WebAssembly with 32-bit pointers - case wasm32 - // WebAssembly with 64-bit pointers - case wasm64 - // 32-bit RenderScript - case renderscript32 - // 64-bit RenderScript - case renderscript64 - - static func parse(_ archName: Substring) -> Triple.Arch? { - switch archName { - case "i386", "i486", "i586", "i686": - return .x86 - case "i786", "i886", "i986": - return .x86 - case "amd64", "x86_64", "x86_64h": - return .x86_64 - case "powerpc", "ppc", "ppc32": - return .ppc - case "powerpc64", "ppu", "ppc64": - return .ppc64 - case "powerpc64le", "ppc64le": - return .ppc64le - case "xscale": - return .arm - case "xscaleeb": - return .armeb - case "aarch64": - return .aarch64 - case "aarch64_be": - return .aarch64_be - case "aarch64_32": - return .aarch64_32 - case "arc": - return .arc - case "arm64": - return .aarch64 - case "arm64e": - return .aarch64e - case "arm64_32": - return .aarch64_32 - case "arm": - return .arm - case "armeb": - return .armeb - case "thumb": - return .thumb - case "thumbeb": - return .thumbeb - case "avr": - return .avr - case "msp430": - return .msp430 - case "mips", "mipseb", "mipsallegrex", "mipsisa32r6", "mipsr6": - return .mips - case "mipsel", "mipsallegrexel", "mipsisa32r6el", "mipsr6el": - return .mipsel - case "mips64", "mips64eb", "mipsn32", "mipsisa64r6", "mips64r6", "mipsn32r6": - return .mips64 - case "mips64el", "mipsn32el", "mipsisa64r6el", "mips64r6el", "mipsn32r6el": - return .mips64el - case "r600": - return .r600 - case "amdgcn": - return .amdgcn - case "riscv32": - return .riscv32 - case "riscv64": - return .riscv64 - case "hexagon": - return .hexagon - case "s390x", "systemz": - return .systemz - case "sparc": - return .sparc - case "sparcel": - return .sparcel - case "sparcv9", "sparc64": - return .sparcv9 - case "tce": - return .tce - case "tcele": - return .tcele - case "xcore": - return .xcore - case "nvptx": - return .nvptx - case "nvptx64": - return .nvptx64 - case "le32": - return .le32 - case "le64": - return .le64 - case "amdil": - return .amdil - case "amdil64": - return .amdil64 - case "hsail": - return .hsail - case "hsail64": - return .hsail64 - case "spir": - return .spir - case "spir64": - return .spir64 - case _ where archName.hasPrefix("kalimba"): - return .kalimba - case "lanai": - return .lanai - case "shave": - return .shave - case "wasm32": - return .wasm32 - case "wasm64": - return .wasm64 - case "renderscript32": - return .renderscript32 - case "renderscript64": - return .renderscript64 - - case _ where archName.hasPrefix("arm") || archName.hasPrefix("thumb") || archName.hasPrefix("aarch64"): - return parseARMArch(archName) - - case _ where archName.hasPrefix("bpf"): - return parseBPFArch(archName) - - default: - return nil - } - } - - enum Endianness { - case big, little - - // Based on LLVM's ARM::parseArchEndian - init?(armArchName archName: S) { - if archName.starts(with: "armeb") || archName.starts(with: "thumbeb") || archName.starts(with: "aarch64_be") { - self = .big - } else if archName.starts(with: "arm") || archName.starts(with: "thumb") { - self = archName.hasSuffix("eb") ? .big : .little - } else if archName.starts(with: "aarch64") || archName.starts(with: "aarch64_32") { - self = .little - } else { - return nil + fileprivate struct ArchInfo: TripleComponent { + var arch: Triple.Arch + var subArch: Triple.SubArch? + + fileprivate static func parse(_ component: Substring) -> ArchInfo? { + // This code assumes that all architectures with a subarch also have an arch. + // This is slightly different from llvm::Triple, whose + // startswith/endswith-based logic might occasionally recognize a subarch + // without an arch, e.g. "xxkalimba5" would have an unknown arch and a + // kalimbav5 subarch. I'm pretty sure that's undesired behavior from LLVM. + + guard let arch = Triple.Arch.parse(component) else { return nil } + return ArchInfo(arch: arch, subArch: Triple.SubArch.parse(component)) } - } } - enum ARMISA { - case aarch64, thumb, arm - - // Based on LLVM's ARM::parseArchISA - init?(archName: S) { - if archName.starts(with: "aarch64") || archName.starts(with: "arm64") { - self = .aarch64 - } else if archName.starts(with: "thumb") { - self = .thumb - } else if archName.starts(with: "arm") { - self = .arm - } else { - return nil + public enum Arch: String, CaseIterable, Decodable, Sendable { + /// ARM (little endian): arm, armv.*, xscale + case arm + // ARM (big endian): armeb + case armeb + /// AArch64 (little endian): aarch64 + case aarch64 + /// AArch64e (little endian): aarch64e + case aarch64e + /// AArch64 (big endian): aarch64_be + case aarch64_be + // AArch64 (little endian) ILP32: aarch64_32 + case aarch64_32 + /// ARC: Synopsis ARC + case arc + /// AVR: Atmel AVR microcontroller + case avr + /// eBPF or extended BPF or 64-bit BPF (little endian) + case bpfel + /// eBPF or extended BPF or 64-bit BPF (big endian) + case bpfeb + /// Hexagon: hexagon + case hexagon + /// MIPS: mips, mipsallegrex, mipsr6 + case mips + /// MIPSEL: mipsel, mipsallegrexe, mipsr6el + case mipsel + // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6 + case mips64 + // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el + case mips64el + // MSP430: msp430 + case msp430 + // PPC: powerpc + case ppc + // PPC64: powerpc64, ppu + case ppc64 + // PPC64LE: powerpc64le + case ppc64le + // R600: AMD GPUs HD2XXX - HD6XXX + case r600 + // AMDGCN: AMD GCN GPUs + case amdgcn + // RISC-V (32-bit): riscv32 + case riscv32 + // RISC-V (64-bit): riscv64 + case riscv64 + // Sparc: sparc + case sparc + // Sparcv9: Sparcv9 + case sparcv9 + // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant + case sparcel + // SystemZ: s390x + case systemz + // TCE (http://tce.cs.tut.fi/): tce + case tce + // TCE little endian (http://tce.cs.tut.fi/): tcele + case tcele + // Thumb (little endian): thumb, thumbv.* + case thumb + // Thumb (big endian): thumbeb + case thumbeb + // X86: i[3-9]86 + case x86 = "i386" + // X86-64: amd64, x86_64 + case x86_64 + // XCore: xcore + case xcore + // NVPTX: 32-bit + case nvptx + // NVPTX: 64-bit + case nvptx64 + // le32: generic little-endian 32-bit CPU (PNaCl) + case le32 + // le64: generic little-endian 64-bit CPU (PNaCl) + case le64 + // AMDIL + case amdil + // AMDIL with 64-bit pointers + case amdil64 + // AMD HSAIL + case hsail + // AMD HSAIL with 64-bit pointers + case hsail64 + // SPIR: standard portable IR for OpenCL 32-bit version + case spir + // SPIR: standard portable IR for OpenCL 64-bit version + case spir64 + // Kalimba: generic kalimba + case kalimba + // SHAVE: Movidius vector VLIW processors + case shave + // Lanai: Lanai 32-bit + case lanai + // WebAssembly with 32-bit pointers + case wasm32 + // WebAssembly with 64-bit pointers + case wasm64 + // 32-bit RenderScript + case renderscript32 + // 64-bit RenderScript + case renderscript64 + + static func parse(_ archName: Substring) -> Triple.Arch? { + switch archName { + case "i386", "i486", "i586", "i686": + return .x86 + case "i786", "i886", "i986": + return .x86 + case "amd64", "x86_64", "x86_64h": + return .x86_64 + case "powerpc", "ppc", "ppc32": + return .ppc + case "powerpc64", "ppu", "ppc64": + return .ppc64 + case "powerpc64le", "ppc64le": + return .ppc64le + case "xscale": + return .arm + case "xscaleeb": + return .armeb + case "aarch64": + return .aarch64 + case "aarch64_be": + return .aarch64_be + case "aarch64_32": + return .aarch64_32 + case "arc": + return .arc + case "arm64": + return .aarch64 + case "arm64e": + return .aarch64e + case "arm64_32": + return .aarch64_32 + case "arm": + return .arm + case "armeb": + return .armeb + case "thumb": + return .thumb + case "thumbeb": + return .thumbeb + case "avr": + return .avr + case "msp430": + return .msp430 + case "mips", "mipseb", "mipsallegrex", "mipsisa32r6", "mipsr6": + return .mips + case "mipsel", "mipsallegrexel", "mipsisa32r6el", "mipsr6el": + return .mipsel + case "mips64", "mips64eb", "mipsn32", "mipsisa64r6", "mips64r6", "mipsn32r6": + return .mips64 + case "mips64el", "mipsn32el", "mipsisa64r6el", "mips64r6el", "mipsn32r6el": + return .mips64el + case "r600": + return .r600 + case "amdgcn": + return .amdgcn + case "riscv32": + return .riscv32 + case "riscv64": + return .riscv64 + case "hexagon": + return .hexagon + case "s390x", "systemz": + return .systemz + case "sparc": + return .sparc + case "sparcel": + return .sparcel + case "sparcv9", "sparc64": + return .sparcv9 + case "tce": + return .tce + case "tcele": + return .tcele + case "xcore": + return .xcore + case "nvptx": + return .nvptx + case "nvptx64": + return .nvptx64 + case "le32": + return .le32 + case "le64": + return .le64 + case "amdil": + return .amdil + case "amdil64": + return .amdil64 + case "hsail": + return .hsail + case "hsail64": + return .hsail64 + case "spir": + return .spir + case "spir64": + return .spir64 + case _ where archName.hasPrefix("kalimba"): + return .kalimba + case "lanai": + return .lanai + case "shave": + return .shave + case "wasm32": + return .wasm32 + case "wasm64": + return .wasm64 + case "renderscript32": + return .renderscript32 + case "renderscript64": + return .renderscript64 + + case _ where archName.hasPrefix("arm") || archName.hasPrefix("thumb") || archName.hasPrefix("aarch64"): + return parseARMArch(archName) + + case _ where archName.hasPrefix("bpf"): + return parseBPFArch(archName) + + default: + return nil + } } - } - } - // Parse ARM architectures not handled by `parse`. On its own, this is not - // enough to correctly parse an ARM architecture. - private static func parseARMArch(_ archName: S) -> Triple.Arch? { - - let ISA = ARMISA(archName: archName) - let endianness = Endianness(armArchName: archName) - - let arch: Triple.Arch? - switch (endianness, ISA) { - case (.little, .arm): - arch = .arm - case (.little, .thumb): - arch = .thumb - case (.little, .aarch64): - arch = .aarch64 - case (.big, .arm): - arch = .armeb - case (.big, .thumb): - arch = .thumbeb - case (.big, .aarch64): - arch = .aarch64_be - case (nil, _), (_, nil): - arch = nil - } - - let cannonicalArchName = cannonicalARMArchName(from: archName) - - if cannonicalArchName.isEmpty { - return nil - } - - // Thumb only exists in v4+ - if ISA == .thumb && (cannonicalArchName.hasPrefix("v2") || cannonicalArchName.hasPrefix("v3")) { - return nil - } - - // Thumb only for v6m - if case .arm(let subArch) = Triple.SubArch.parse(archName), subArch.profile == .m && subArch.version == 6 { - if endianness == .big { - return .thumbeb - } else { - return .thumb + enum Endianness { + case big, little + + // Based on LLVM's ARM::parseArchEndian + init?(armArchName archName: S) { + if archName.starts(with: "armeb") || archName.starts(with: "thumbeb") || archName.starts(with: "aarch64_be") { + self = .big + } else if archName.starts(with: "arm") || archName.starts(with: "thumb") { + self = archName.hasSuffix("eb") ? .big : .little + } else if archName.starts(with: "aarch64") || archName.starts(with: "aarch64_32") { + self = .little + } else { + return nil + } + } } - } - return arch - } - - // Based on LLVM's ARM::getCanonicalArchName - // - // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but - // (iwmmxt|xscale)(eb)? is also permitted. If the former, return - // "v.+", if the latter, return unmodified string, minus 'eb'. - // If invalid, return empty string. - fileprivate static func cannonicalARMArchName(from arch: S) -> String { - var name = Substring(arch) - - func dropPrefix(_ prefix: String) { - if name.hasPrefix(prefix) { - name = name.dropFirst(prefix.count) + enum ARMISA { + case aarch64, thumb, arm + + // Based on LLVM's ARM::parseArchISA + init?(archName: S) { + if archName.starts(with: "aarch64") || archName.starts(with: "arm64") { + self = .aarch64 + } else if archName.starts(with: "thumb") { + self = .thumb + } else if archName.starts(with: "arm") { + self = .arm + } else { + return nil + } + } } - } - - let possiblePrefixes = ["arm64_32", "arm64", "aarch64_32", "arm", "thumb", "aarch64"] - - if let prefix = possiblePrefixes.first(where: name.hasPrefix) { - dropPrefix(prefix) - if prefix == "aarch64" { - // AArch64 uses "_be", not "eb" suffix. - if name.contains("eb") { - return "" - } - - dropPrefix("_be") - } - } - - // Ex. "armebv7", move past the "eb". - if name != arch { - dropPrefix("eb") - } - // Or, if it ends with eb ("armv7eb"), chop it off. - else if name.hasSuffix("eb") { - name = name.dropLast(2) - } - - // Reached the end - arch is valid. - if name.isEmpty { - return String(arch) - } - - // Only match non-marketing names - if name != arch { - // Must start with 'vN'. - if name.count >= 2 && (name.first != "v" || !name.dropFirst().first!.isNumber) { - return "" + // Parse ARM architectures not handled by `parse`. On its own, this is not + // enough to correctly parse an ARM architecture. + private static func parseARMArch(_ archName: S) -> Triple.Arch? { + + let ISA = ARMISA(archName: archName) + let endianness = Endianness(armArchName: archName) + + let arch: Triple.Arch? + switch (endianness, ISA) { + case (.little, .arm): + arch = .arm + case (.little, .thumb): + arch = .thumb + case (.little, .aarch64): + arch = .aarch64 + case (.big, .arm): + arch = .armeb + case (.big, .thumb): + arch = .thumbeb + case (.big, .aarch64): + arch = .aarch64_be + case (nil, _), (_, nil): + arch = nil + } + + let cannonicalArchName = cannonicalARMArchName(from: archName) + + if cannonicalArchName.isEmpty { + return nil + } + + // Thumb only exists in v4+ + if ISA == .thumb && (cannonicalArchName.hasPrefix("v2") || cannonicalArchName.hasPrefix("v3")) { + return nil + } + + // Thumb only for v6m + if case .arm(let subArch) = Triple.SubArch.parse(archName), subArch.profile == .m && subArch.version == 6 { + if endianness == .big { + return .thumbeb + } else { + return .thumb + } + } + + return arch } - // Can't have an extra 'eb'. - if name.hasPrefix("eb") { - return "" + // Based on LLVM's ARM::getCanonicalArchName + // + // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but + // (iwmmxt|xscale)(eb)? is also permitted. If the former, return + // "v.+", if the latter, return unmodified string, minus 'eb'. + // If invalid, return empty string. + fileprivate static func cannonicalARMArchName(from arch: S) -> String { + var name = Substring(arch) + + func dropPrefix(_ prefix: String) { + if name.hasPrefix(prefix) { + name = name.dropFirst(prefix.count) + } + } + + let possiblePrefixes = ["arm64_32", "arm64", "aarch64_32", "arm", "thumb", "aarch64"] + + if let prefix = possiblePrefixes.first(where: name.hasPrefix) { + dropPrefix(prefix) + + if prefix == "aarch64" { + // AArch64 uses "_be", not "eb" suffix. + if name.contains("eb") { + return "" + } + + dropPrefix("_be") + } + } + + // Ex. "armebv7", move past the "eb". + if name != arch { + dropPrefix("eb") + } + // Or, if it ends with eb ("armv7eb"), chop it off. + else if name.hasSuffix("eb") { + name = name.dropLast(2) + } + + // Reached the end - arch is valid. + if name.isEmpty { + return String(arch) + } + + // Only match non-marketing names + if name != arch { + // Must start with 'vN'. + if name.count >= 2 && (name.first != "v" || !name.dropFirst().first!.isNumber) { + return "" + } + + // Can't have an extra 'eb'. + if name.hasPrefix("eb") { + return "" + } + } + + // Arch will either be a 'v' name (v7a) or a marketing name (xscale). + return String(name) } - } - - // Arch will either be a 'v' name (v7a) or a marketing name (xscale). - return String(name) - } - private static func parseBPFArch(_ archName: S) -> Triple.Arch? { + private static func parseBPFArch(_ archName: S) -> Triple.Arch? { - let isLittleEndianHost = 1.littleEndian == 1 + let isLittleEndianHost = 1.littleEndian == 1 - switch archName { - case "bpf": - return isLittleEndianHost ? .bpfel : .bpfeb - case "bpf_be", "bpfeb": - return .bpfeb - case "bpf_le", "bpfel": - return .bpfel - default: - return nil - } - } + switch archName { + case "bpf": + return isLittleEndianHost ? .bpfel : .bpfeb + case "bpf_be", "bpfeb": + return .bpfeb + case "bpf_le", "bpfel": + return .bpfel + default: + return nil + } + } - /// Whether or not this architecture has 64-bit pointers - public var is64Bit: Bool { pointerBitWidth == 64 } + /// Whether or not this architecture has 64-bit pointers + public var is64Bit: Bool { pointerBitWidth == 64 } - /// Whether or not this architecture has 32-bit pointers - public var is32Bit: Bool { pointerBitWidth == 32 } + /// Whether or not this architecture has 32-bit pointers + public var is32Bit: Bool { pointerBitWidth == 32 } - /// Whether or not this architecture has 16-bit pointers - public var is16Bit: Bool { pointerBitWidth == 16 } + /// Whether or not this architecture has 16-bit pointers + public var is16Bit: Bool { pointerBitWidth == 16 } - /// The width in bits of pointers on this architecture. - var pointerBitWidth: Int { - switch self { - case .avr, .msp430: - return 16 + /// The width in bits of pointers on this architecture. + var pointerBitWidth: Int { + switch self { + case .avr, .msp430: + return 16 - case .arc, .arm, .armeb, .hexagon, .le32, .mips, .mipsel, .nvptx, - .ppc, .r600, .riscv32, .sparc, .sparcel, .tce, .tcele, .thumb, - .thumbeb, .x86, .xcore, .amdil, .hsail, .spir, .kalimba,.lanai, - .shave, .wasm32, .renderscript32, .aarch64_32: - return 32 + case .arc, .arm, .armeb, .hexagon, .le32, .mips, .mipsel, .nvptx, + .ppc, .r600, .riscv32, .sparc, .sparcel, .tce, .tcele, .thumb, + .thumbeb, .x86, .xcore, .amdil, .hsail, .spir, .kalimba, .lanai, + .shave, .wasm32, .renderscript32, .aarch64_32: + return 32 - case .aarch64, .aarch64e, .aarch64_be, .amdgcn, .bpfel, .bpfeb, .le64, .mips64, - .mips64el, .nvptx64, .ppc64, .ppc64le, .riscv64, .sparcv9, .systemz, - .x86_64, .amdil64, .hsail64, .spir64, .wasm64, .renderscript64: - return 64 - } + case .aarch64, .aarch64e, .aarch64_be, .amdgcn, .bpfel, .bpfeb, .le64, .mips64, + .mips64el, .nvptx64, .ppc64, .ppc64le, .riscv64, .sparcv9, .systemz, + .x86_64, .amdil64, .hsail64, .spir64, .wasm64, .renderscript64: + return 64 + } + } } - } } // MARK: - Parse SubArch @@ -846,873 +856,877 @@ public enum Arch: String, CaseIterable, Decodable, Sendable { extension Triple { public enum SubArch: Hashable, Sendable { - public enum ARM: Sendable { - - public enum Profile { - case a, r, m - } - - case v2 - case v2a - case v3 - case v3m - case v4 - case v4t - case v5 - case v5e - case v6 - case v6k - case v6kz - case v6m - case v6t2 - case v7 - case v7em - case v7k - case v7m - case v7r - case v7s - case v7ve - case v8 - case v8_1a - case v8_1m_mainline - case v8_2a - case v8_3a - case v8_4a - case v8_5a - case v8m_baseline - case v8m_mainline - case v8r - - var profile: Triple.SubArch.ARM.Profile? { - switch self { - case .v6m, .v7m, .v7em, .v8m_mainline, .v8m_baseline, .v8_1m_mainline: - return .m - case .v7r, .v8r: - return .r - case .v7, .v7ve, .v7k, .v8, .v8_1a, .v8_2a, .v8_3a, .v8_4a, .v8_5a: - return .a - case .v2, .v2a, .v3, .v3m, .v4, .v4t, .v5, .v5e, .v6, .v6k, .v6kz, .v6t2, .v7s: - return nil - } - } - - var version: Int { - switch self { - case .v2, .v2a: - return 2 - case .v3, .v3m: - return 3 - case .v4, .v4t: - return 4 - case .v5, .v5e: - return 5 - case .v6, .v6k, .v6kz, .v6m, .v6t2: - return 6 - case .v7, .v7em, .v7k, .v7m, .v7r, .v7s, .v7ve: - return 7 - case .v8, .v8_1a, .v8_1m_mainline, .v8_2a, .v8_3a, .v8_4a, .v8_5a, .v8m_baseline, .v8m_mainline, .v8r: - return 8 + public enum ARM: Sendable { + + public enum Profile { + case a, r, m + } + + case v2 + case v2a + case v3 + case v3m + case v4 + case v4t + case v5 + case v5e + case v6 + case v6k + case v6kz + case v6m + case v6t2 + case v7 + case v7em + case v7k + case v7m + case v7r + case v7s + case v7ve + case v8 + case v8_1a + case v8_1m_mainline + case v8_2a + case v8_3a + case v8_4a + case v8_5a + case v8m_baseline + case v8m_mainline + case v8r + + var profile: Triple.SubArch.ARM.Profile? { + switch self { + case .v6m, .v7m, .v7em, .v8m_mainline, .v8m_baseline, .v8_1m_mainline: + return .m + case .v7r, .v8r: + return .r + case .v7, .v7ve, .v7k, .v8, .v8_1a, .v8_2a, .v8_3a, .v8_4a, .v8_5a: + return .a + case .v2, .v2a, .v3, .v3m, .v4, .v4t, .v5, .v5e, .v6, .v6k, .v6kz, .v6t2, .v7s: + return nil + } + } + + var version: Int { + switch self { + case .v2, .v2a: + return 2 + case .v3, .v3m: + return 3 + case .v4, .v4t: + return 4 + case .v5, .v5e: + return 5 + case .v6, .v6k, .v6kz, .v6m, .v6t2: + return 6 + case .v7, .v7em, .v7k, .v7m, .v7r, .v7s, .v7ve: + return 7 + case .v8, .v8_1a, .v8_1m_mainline, .v8_2a, .v8_3a, .v8_4a, .v8_5a, .v8m_baseline, .v8m_mainline, .v8r: + return 8 + } + } } - } - } - - public enum Kalimba: Sendable { - case v3 - case v4 - case v5 - } - public enum MIPS: Sendable { - case r6 - } - - case arm(ARM) - case kalimba(Kalimba) - case mips(MIPS) - - fileprivate static func parse(_ component: S) -> Triple.SubArch? { - - if component.hasPrefix("mips") && (component.hasSuffix("r6el") || component.hasSuffix("r6")) { - return .mips(.r6) - } + public enum Kalimba: Sendable { + case v3 + case v4 + case v5 + } - let armSubArch = Triple.Arch.cannonicalARMArchName(from: component) + public enum MIPS: Sendable { + case r6 + } - if armSubArch.isEmpty { - switch component { - case _ where component.hasSuffix("kalimba3"): - return .kalimba(.v3) - case _ where component.hasSuffix("kalimba4"): - return .kalimba(.v4) - case _ where component.hasSuffix("kalimba5"): - return .kalimba(.v5) - default: - return nil + case arm(ARM) + case kalimba(Kalimba) + case mips(MIPS) + + fileprivate static func parse(_ component: S) -> Triple.SubArch? { + + if component.hasPrefix("mips") && (component.hasSuffix("r6el") || component.hasSuffix("r6")) { + return .mips(.r6) + } + + let armSubArch = Triple.Arch.cannonicalARMArchName(from: component) + + if armSubArch.isEmpty { + switch component { + case _ where component.hasSuffix("kalimba3"): + return .kalimba(.v3) + case _ where component.hasSuffix("kalimba4"): + return .kalimba(.v4) + case _ where component.hasSuffix("kalimba5"): + return .kalimba(.v5) + default: + return nil + } + } + + switch armSubArch { + case "v2": + return .arm(.v2) + case "v2a": + return .arm(.v2a) + case "v3": + return .arm(.v3) + case "v3m": + return .arm(.v3m) + case "v4": + return .arm(.v4) + case "v4t": + return .arm(.v4t) + case "v5t": + return .arm(.v5) + case "v5te", "v5tej", "xscale": + return .arm(.v5e) + case "v6": + return .arm(.v6) + case "v6k": + return .arm(.v6k) + case "v6kz": + return .arm(.v6kz) + case "v6m", "v6-m": + return .arm(.v6m) + case "v6t2": + return .arm(.v6t2) + case "v7a", "v7-a": + return .arm(.v7) + case "v7k": + return .arm(.v7k) + case "v7m", "v7-m": + return .arm(.v7m) + case "v7em", "v7e-m": + return .arm(.v7em) + case "v7r", "v7-r": + return .arm(.v7r) + case "v7s": + return .arm(.v7s) + case "v7ve": + return .arm(.v7ve) + case "v8-a": + return .arm(.v8) + case "v8-m.main": + return .arm(.v8m_mainline) + case "v8-m.base": + return .arm(.v8m_baseline) + case "v8-r": + return .arm(.v8r) + case "v8.1-m.main": + return .arm(.v8_1m_mainline) + case "v8.1-a": + return .arm(.v8_1a) + case "v8.2-a": + return .arm(.v8_2a) + case "v8.3-a": + return .arm(.v8_3a) + case "v8.4-a": + return .arm(.v8_4a) + case "v8.5-a": + return .arm(.v8_5a) + default: + return nil + } } - } - - switch armSubArch { - case "v2": - return .arm(.v2) - case "v2a": - return .arm(.v2a) - case "v3": - return .arm(.v3) - case "v3m": - return .arm(.v3m) - case "v4": - return .arm(.v4) - case "v4t": - return .arm(.v4t) - case "v5t": - return .arm(.v5) - case "v5te", "v5tej", "xscale": - return .arm(.v5e) - case "v6": - return .arm(.v6) - case "v6k": - return .arm(.v6k) - case "v6kz": - return .arm(.v6kz) - case "v6m", "v6-m": - return .arm(.v6m) - case "v6t2": - return .arm(.v6t2) - case "v7a", "v7-a": - return .arm(.v7) - case "v7k": - return .arm(.v7k) - case "v7m", "v7-m": - return .arm(.v7m) - case "v7em", "v7e-m": - return .arm(.v7em) - case "v7r", "v7-r": - return .arm(.v7r) - case "v7s": - return .arm(.v7s) - case "v7ve": - return .arm(.v7ve) - case "v8-a": - return .arm(.v8) - case "v8-m.main": - return .arm(.v8m_mainline) - case "v8-m.base": - return .arm(.v8m_baseline) - case "v8-r": - return .arm(.v8r) - case "v8.1-m.main": - return .arm(.v8_1m_mainline) - case "v8.1-a": - return .arm(.v8_1a) - case "v8.2-a": - return .arm(.v8_2a) - case "v8.3-a": - return .arm(.v8_3a) - case "v8.4-a": - return .arm(.v8_4a) - case "v8.5-a": - return .arm(.v8_5a) - default: - return nil - } } - } } // MARK: - Parse Vendor extension Triple { public enum Vendor: String, CaseIterable, TripleComponent, Sendable { - case apple - case pc - case scei - case bgp - case bgq - case freescale = "fsl" - case ibm - case imaginationTechnologies = "img" - case mipsTechnologies = "mti" - case nvidia - case csr - case myriad - case amd - case mesa - case suse - case openEmbedded = "oe" - - fileprivate static func parse(_ component: Substring) -> Triple.Vendor? { - switch component { - case "apple": - return .apple - case "pc": - return .pc - case "scei": - return .scei - case "bgp": - return .bgp - case "bgq": - return .bgq - case "fsl": - return .freescale - case "ibm": - return .ibm - case "img": - return .imaginationTechnologies - case "mti": - return .mipsTechnologies - case "nvidia": - return .nvidia - case "csr": - return .csr - case "myriad": - return .myriad - case "amd": - return .amd - case "mesa": - return .mesa - case "suse": - return .suse - case "oe": - return .openEmbedded - default: - return nil - } + case apple + case pc + case scei + case bgp + case bgq + case freescale = "fsl" + case ibm + case imaginationTechnologies = "img" + case mipsTechnologies = "mti" + case nvidia + case csr + case myriad + case amd + case mesa + case suse + case openEmbedded = "oe" + + fileprivate static func parse(_ component: Substring) -> Triple.Vendor? { + switch component { + case "apple": + return .apple + case "pc": + return .pc + case "scei": + return .scei + case "bgp": + return .bgp + case "bgq": + return .bgq + case "fsl": + return .freescale + case "ibm": + return .ibm + case "img": + return .imaginationTechnologies + case "mti": + return .mipsTechnologies + case "nvidia": + return .nvidia + case "csr": + return .csr + case "myriad": + return .myriad + case "amd": + return .amd + case "mesa": + return .mesa + case "suse": + return .suse + case "oe": + return .openEmbedded + default: + return nil + } + } } - } } // MARK: - Parse OS extension Triple { - public enum OS: String, CaseIterable, TripleComponent, Sendable { - case ananas - case cloudABI = "cloudabi" - case darwin - case dragonFly = "dragonfly" - case freebsd = "freebsd" - case fuchsia - case ios - case kfreebsd - case linux - case lv2 - case macosx - case netbsd - case openbsd - case solaris - case win32 - case haiku - case minix - case rtems - case nacl - case cnk - case aix - case cuda - case nvcl - case amdhsa - case ps4 - case elfiamcu - case tvos - case watchos - case mesa3d - case contiki - case amdpal - case hermitcore - case hurd - case wasi - case emscripten - case noneOS // 'OS' suffix purely to avoid name clash with Optional.none - - var name: String { - return rawValue - } + public enum OS: String, CaseIterable, TripleComponent, Sendable { + case ananas + case cloudABI = "cloudabi" + case darwin + case dragonFly = "dragonfly" + case freebsd = "freebsd" + case fuchsia + case ios + case kfreebsd + case linux + case lv2 + case macosx + case netbsd + case openbsd + case solaris + case win32 + case haiku + case minix + case rtems + case nacl + case cnk + case aix + case cuda + case nvcl + case amdhsa + case ps4 + case elfiamcu + case tvos + case watchos + case mesa3d + case contiki + case amdpal + case hermitcore + case hurd + case wasi + case emscripten + case noneOS // 'OS' suffix purely to avoid name clash with Optional.none + + var name: String { + return rawValue + } - fileprivate static func parse(_ os: Substring) -> Triple.OS? { - switch os { - case _ where os.hasPrefix("ananas"): - return .ananas - case _ where os.hasPrefix("cloudabi"): - return .cloudABI - case _ where os.hasPrefix("darwin"): - return .darwin - case _ where os.hasPrefix("dragonfly"): - return .dragonFly - case _ where os.hasPrefix("freebsd"): - return .freebsd - case _ where os.hasPrefix("fuchsia"): - return .fuchsia - case _ where os.hasPrefix("ios"): - return .ios - case _ where os.hasPrefix("kfreebsd"): - return .kfreebsd - case _ where os.hasPrefix("linux"): - return .linux - case _ where os.hasPrefix("lv2"): - return .lv2 - case _ where os.hasPrefix("macos"): - return .macosx - case _ where os.hasPrefix("netbsd"): - return .netbsd - case _ where os.hasPrefix("openbsd"): - return .openbsd - case _ where os.hasPrefix("solaris"): - return .solaris - case _ where os.hasPrefix("win32"): - return .win32 - case _ where os.hasPrefix("windows"): - return .win32 - case _ where os.hasPrefix("haiku"): - return .haiku - case _ where os.hasPrefix("minix"): - return .minix - case _ where os.hasPrefix("rtems"): - return .rtems - case _ where os.hasPrefix("nacl"): - return .nacl - case _ where os.hasPrefix("cnk"): - return .cnk - case _ where os.hasPrefix("aix"): - return .aix - case _ where os.hasPrefix("cuda"): - return .cuda - case _ where os.hasPrefix("nvcl"): - return .nvcl - case _ where os.hasPrefix("amdhsa"): - return .amdhsa - case _ where os.hasPrefix("ps4"): - return .ps4 - case _ where os.hasPrefix("elfiamcu"): - return .elfiamcu - case _ where os.hasPrefix("tvos"): - return .tvos - case _ where os.hasPrefix("watchos"): - return .watchos - case _ where os.hasPrefix("mesa3d"): - return .mesa3d - case _ where os.hasPrefix("contiki"): - return .contiki - case _ where os.hasPrefix("amdpal"): - return .amdpal - case _ where os.hasPrefix("hermit"): - return .hermitcore - case _ where os.hasPrefix("hurd"): - return .hurd - case _ where os.hasPrefix("wasi"): - return .wasi - case _ where os.hasPrefix("emscripten"): - return .emscripten - case _ where os.hasPrefix("none"): - return .noneOS - default: - return nil - } - } + fileprivate static func parse(_ os: Substring) -> Triple.OS? { + switch os { + case _ where os.hasPrefix("ananas"): + return .ananas + case _ where os.hasPrefix("cloudabi"): + return .cloudABI + case _ where os.hasPrefix("darwin"): + return .darwin + case _ where os.hasPrefix("dragonfly"): + return .dragonFly + case _ where os.hasPrefix("freebsd"): + return .freebsd + case _ where os.hasPrefix("fuchsia"): + return .fuchsia + case _ where os.hasPrefix("ios"): + return .ios + case _ where os.hasPrefix("kfreebsd"): + return .kfreebsd + case _ where os.hasPrefix("linux"): + return .linux + case _ where os.hasPrefix("lv2"): + return .lv2 + case _ where os.hasPrefix("macos"): + return .macosx + case _ where os.hasPrefix("netbsd"): + return .netbsd + case _ where os.hasPrefix("openbsd"): + return .openbsd + case _ where os.hasPrefix("solaris"): + return .solaris + case _ where os.hasPrefix("win32"): + return .win32 + case _ where os.hasPrefix("windows"): + return .win32 + case _ where os.hasPrefix("haiku"): + return .haiku + case _ where os.hasPrefix("minix"): + return .minix + case _ where os.hasPrefix("rtems"): + return .rtems + case _ where os.hasPrefix("nacl"): + return .nacl + case _ where os.hasPrefix("cnk"): + return .cnk + case _ where os.hasPrefix("aix"): + return .aix + case _ where os.hasPrefix("cuda"): + return .cuda + case _ where os.hasPrefix("nvcl"): + return .nvcl + case _ where os.hasPrefix("amdhsa"): + return .amdhsa + case _ where os.hasPrefix("ps4"): + return .ps4 + case _ where os.hasPrefix("elfiamcu"): + return .elfiamcu + case _ where os.hasPrefix("tvos"): + return .tvos + case _ where os.hasPrefix("watchos"): + return .watchos + case _ where os.hasPrefix("mesa3d"): + return .mesa3d + case _ where os.hasPrefix("contiki"): + return .contiki + case _ where os.hasPrefix("amdpal"): + return .amdpal + case _ where os.hasPrefix("hermit"): + return .hermitcore + case _ where os.hasPrefix("hurd"): + return .hurd + case _ where os.hasPrefix("wasi"): + return .wasi + case _ where os.hasPrefix("emscripten"): + return .emscripten + case _ where os.hasPrefix("none"): + return .noneOS + default: + return nil + } + } - fileprivate static func valueIsValid(_ value: Substring) -> Bool { - parse(value) != nil || value.hasPrefix("cygwin") || value.hasPrefix("mingw") + fileprivate static func valueIsValid(_ value: Substring) -> Bool { + parse(value) != nil || value.hasPrefix("cygwin") || value.hasPrefix("mingw") + } } - } } // MARK: - Parse Environment extension Triple { - fileprivate enum EnvInfo: TripleComponent { - case environmentOnly(Triple.Environment) - case objectFormatOnly(Triple.ObjectFormat) - case both( - environment: Triple.Environment, - objectFormat: Triple.ObjectFormat - ) - - var environment: Triple.Environment? { - switch self { - case .environmentOnly(let env), .both(let env, _): - return env - case .objectFormatOnly: - return nil - } - } - var objectFormat: Triple.ObjectFormat? { - switch self { - case .objectFormatOnly(let obj), .both(_, let obj): - return obj - case .environmentOnly: - return nil - } - } + fileprivate enum EnvInfo: TripleComponent { + case environmentOnly(Triple.Environment) + case objectFormatOnly(Triple.ObjectFormat) + case both( + environment: Triple.Environment, + objectFormat: Triple.ObjectFormat + ) + + var environment: Triple.Environment? { + switch self { + case .environmentOnly(let env), .both(let env, _): + return env + case .objectFormatOnly: + return nil + } + } + var objectFormat: Triple.ObjectFormat? { + switch self { + case .objectFormatOnly(let obj), .both(_, let obj): + return obj + case .environmentOnly: + return nil + } + } - fileprivate static func parse(_ component: Substring) -> EnvInfo? { - switch ( - Triple.Environment.parse(component), - Triple.ObjectFormat.parse(component) - ) { - case (nil, nil): - return nil - case (nil, let obj?): - return .objectFormatOnly(obj) - case (let env?, nil): - return .environmentOnly(env) - case (let env?, let obj?): - return .both(environment: env, objectFormat: obj) - } - } - } - - public enum Environment: String, CaseIterable, Equatable, Sendable { - case eabihf - case eabi - case elfv1 - case elfv2 - case gnuabin32 - case gnuabi64 - case gnueabihf - case gnueabi - case gnux32 - case code16 - case gnu - case android - case musleabihf - case musleabi - case musl - case msvc - case itanium - case cygnus - case coreclr - case simulator - case macabi - - fileprivate static func parse(_ env: Substring) -> Triple.Environment? { - switch env { - case _ where env.hasPrefix("eabihf"): - return .eabihf - case _ where env.hasPrefix("eabi"): - return .eabi - case _ where env.hasPrefix("elfv1"): - return .elfv1 - case _ where env.hasPrefix("elfv2"): - return .elfv2 - case _ where env.hasPrefix("gnuabin32"): - return .gnuabin32 - case _ where env.hasPrefix("gnuabi64"): - return .gnuabi64 - case _ where env.hasPrefix("gnueabihf"): - return .gnueabihf - case _ where env.hasPrefix("gnueabi"): - return .gnueabi - case _ where env.hasPrefix("gnux32"): - return .gnux32 - case _ where env.hasPrefix("code16"): - return .code16 - case _ where env.hasPrefix("gnu"): - return .gnu - case _ where env.hasPrefix("android"): - return .android - case _ where env.hasPrefix("musleabihf"): - return .musleabihf - case _ where env.hasPrefix("musleabi"): - return .musleabi - case _ where env.hasPrefix("musl"): - return .musl - case _ where env.hasPrefix("msvc"): - return .msvc - case _ where env.hasPrefix("itanium"): - return .itanium - case _ where env.hasPrefix("cygnus"): - return .cygnus - case _ where env.hasPrefix("coreclr"): - return .coreclr - case _ where env.hasPrefix("simulator"): - return .simulator - case _ where env.hasPrefix("macabi"): - return .macabi - default: - return nil - } + fileprivate static func parse(_ component: Substring) -> EnvInfo? { + switch ( + Triple.Environment.parse(component), + Triple.ObjectFormat.parse(component) + ) { + case (nil, nil): + return nil + case (nil, let obj?): + return .objectFormatOnly(obj) + case (let env?, nil): + return .environmentOnly(env) + case (let env?, let obj?): + return .both(environment: env, objectFormat: obj) + } + } } - fileprivate static func infer(archName: Substring?) -> Triple.Environment? { - guard let firstComponent = archName else { return nil } - - switch firstComponent { - case _ where firstComponent.hasPrefix("mipsn32"): - return .gnuabin32 - case _ where firstComponent.hasPrefix("mips64"): - return .gnuabi64 - case _ where firstComponent.hasPrefix("mipsisa64"): - return .gnuabi64 - case _ where firstComponent.hasPrefix("mipsisa32"): - return .gnu - case "mips", "mipsel", "mipsr6", "mipsr6el": - return .gnu - default: - return nil - } + public enum Environment: String, CaseIterable, Equatable, Sendable { + case eabihf + case eabi + case elfv1 + case elfv2 + case gnuabin32 + case gnuabi64 + case gnueabihf + case gnueabi + case gnux32 + case code16 + case gnu + case android + case musleabihf + case musleabi + case musl + case msvc + case itanium + case cygnus + case coreclr + case simulator + case macabi + + fileprivate static func parse(_ env: Substring) -> Triple.Environment? { + switch env { + case _ where env.hasPrefix("eabihf"): + return .eabihf + case _ where env.hasPrefix("eabi"): + return .eabi + case _ where env.hasPrefix("elfv1"): + return .elfv1 + case _ where env.hasPrefix("elfv2"): + return .elfv2 + case _ where env.hasPrefix("gnuabin32"): + return .gnuabin32 + case _ where env.hasPrefix("gnuabi64"): + return .gnuabi64 + case _ where env.hasPrefix("gnueabihf"): + return .gnueabihf + case _ where env.hasPrefix("gnueabi"): + return .gnueabi + case _ where env.hasPrefix("gnux32"): + return .gnux32 + case _ where env.hasPrefix("code16"): + return .code16 + case _ where env.hasPrefix("gnu"): + return .gnu + case _ where env.hasPrefix("android"): + return .android + case _ where env.hasPrefix("musleabihf"): + return .musleabihf + case _ where env.hasPrefix("musleabi"): + return .musleabi + case _ where env.hasPrefix("musl"): + return .musl + case _ where env.hasPrefix("msvc"): + return .msvc + case _ where env.hasPrefix("itanium"): + return .itanium + case _ where env.hasPrefix("cygnus"): + return .cygnus + case _ where env.hasPrefix("coreclr"): + return .coreclr + case _ where env.hasPrefix("simulator"): + return .simulator + case _ where env.hasPrefix("macabi"): + return .macabi + default: + return nil + } + } + + fileprivate static func infer(archName: Substring?) -> Triple.Environment? { + guard let firstComponent = archName else { return nil } + + switch firstComponent { + case _ where firstComponent.hasPrefix("mipsn32"): + return .gnuabin32 + case _ where firstComponent.hasPrefix("mips64"): + return .gnuabi64 + case _ where firstComponent.hasPrefix("mipsisa64"): + return .gnuabi64 + case _ where firstComponent.hasPrefix("mipsisa32"): + return .gnu + case "mips", "mipsel", "mipsr6", "mipsr6el": + return .gnu + default: + return nil + } + } } - } } // MARK: - Parse Object Format extension Triple { - public enum ObjectFormat: Sendable { - case coff - case elf - case macho - case wasm - case xcoff - - fileprivate static func parse(_ env: Substring) -> Triple.ObjectFormat? { - switch env { - // "xcoff" must come before "coff" because of the order-dependendent pattern matching. - case _ where env.hasSuffix("xcoff"): - return .xcoff - case _ where env.hasSuffix("coff"): - return .coff - case _ where env.hasSuffix("elf"): - return .elf - case _ where env.hasSuffix("macho"): - return .macho - case _ where env.hasSuffix("wasm"): - return .wasm - default: - return nil - } - } + public enum ObjectFormat: Sendable { + case coff + case elf + case macho + case wasm + case xcoff + + fileprivate static func parse(_ env: Substring) -> Triple.ObjectFormat? { + switch env { + // "xcoff" must come before "coff" because of the order-dependendent pattern matching. + case _ where env.hasSuffix("xcoff"): + return .xcoff + case _ where env.hasSuffix("coff"): + return .coff + case _ where env.hasSuffix("elf"): + return .elf + case _ where env.hasSuffix("macho"): + return .macho + case _ where env.hasSuffix("wasm"): + return .wasm + default: + return nil + } + } - fileprivate static func infer(arch: Triple.Arch?, os: Triple.OS?) -> Triple.ObjectFormat { - switch arch { - case nil, .aarch64, .aarch64e, .aarch64_32, .arm, .thumb, .x86, .x86_64: - if os?.isDarwin ?? false { - return .macho - } else if os?.isWindows ?? false { - return .coff - } - return .elf - - case .aarch64_be: fallthrough - case .arc: fallthrough - case .amdgcn: fallthrough - case .amdil: fallthrough - case .amdil64: fallthrough - case .armeb: fallthrough - case .avr: fallthrough - case .bpfeb: fallthrough - case .bpfel: fallthrough - case .hexagon: fallthrough - case .lanai: fallthrough - case .hsail: fallthrough - case .hsail64: fallthrough - case .kalimba: fallthrough - case .le32: fallthrough - case .le64: fallthrough - case .mips: fallthrough - case .mips64: fallthrough - case .mips64el: fallthrough - case .mipsel: fallthrough - case .msp430: fallthrough - case .nvptx: fallthrough - case .nvptx64: fallthrough - case .ppc64le: fallthrough - case .r600: fallthrough - case .renderscript32: fallthrough - case .renderscript64: fallthrough - case .riscv32: fallthrough - case .riscv64: fallthrough - case .shave: fallthrough - case .sparc: fallthrough - case .sparcel: fallthrough - case .sparcv9: fallthrough - case .spir: fallthrough - case .spir64: fallthrough - case .systemz: fallthrough - case .tce: fallthrough - case .tcele: fallthrough - case .thumbeb: fallthrough - case .xcore: - return .elf - - case .ppc, .ppc64: - if os?.isDarwin ?? false { - return .macho - } else if os == .aix { - return .xcoff - } - return .elf - - case .wasm32, .wasm64: - return .wasm - } - } + fileprivate static func infer(arch: Triple.Arch?, os: Triple.OS?) -> Triple.ObjectFormat { + switch arch { + case nil, .aarch64, .aarch64e, .aarch64_32, .arm, .thumb, .x86, .x86_64: + if os?.isDarwin ?? false { + return .macho + } else if os?.isWindows ?? false { + return .coff + } + return .elf + + case .aarch64_be: fallthrough + case .arc: fallthrough + case .amdgcn: fallthrough + case .amdil: fallthrough + case .amdil64: fallthrough + case .armeb: fallthrough + case .avr: fallthrough + case .bpfeb: fallthrough + case .bpfel: fallthrough + case .hexagon: fallthrough + case .lanai: fallthrough + case .hsail: fallthrough + case .hsail64: fallthrough + case .kalimba: fallthrough + case .le32: fallthrough + case .le64: fallthrough + case .mips: fallthrough + case .mips64: fallthrough + case .mips64el: fallthrough + case .mipsel: fallthrough + case .msp430: fallthrough + case .nvptx: fallthrough + case .nvptx64: fallthrough + case .ppc64le: fallthrough + case .r600: fallthrough + case .renderscript32: fallthrough + case .renderscript64: fallthrough + case .riscv32: fallthrough + case .riscv64: fallthrough + case .shave: fallthrough + case .sparc: fallthrough + case .sparcel: fallthrough + case .sparcv9: fallthrough + case .spir: fallthrough + case .spir64: fallthrough + case .systemz: fallthrough + case .tce: fallthrough + case .tcele: fallthrough + case .thumbeb: fallthrough + case .xcore: + return .elf + + case .ppc, .ppc64: + if os?.isDarwin ?? false { + return .macho + } else if os == .aix { + return .xcoff + } + return .elf + + case .wasm32, .wasm64: + return .wasm + } + } - var name: String { - switch self { - case .coff: return "coff" - case .elf: return "elf" - case .macho: return "macho" - case .wasm: return "wasm" - case .xcoff: return "xcoff" - } + var name: String { + switch self { + case .coff: return "coff" + case .elf: return "elf" + case .macho: return "macho" + case .wasm: return "wasm" + case .xcoff: return "xcoff" + } + } } - } } // MARK: - OS tests extension Triple.OS { - public var isWindows: Bool { - self == .win32 - } - - public var isAIX: Bool { - self == .aix - } - - /// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both - /// "darwin" and "osx" as OS X triples. - public var isMacOSX: Bool { - self == .darwin || self == .macosx - } - - /// Is this an iOS triple. - /// Note: This identifies tvOS as a variant of iOS. If that ever - /// changes, i.e., if the two operating systems diverge or their version - /// numbers get out of sync, that will need to be changed. - /// watchOS has completely different version numbers so it is not included. - public var isiOS: Bool { - self == .ios || isTvOS - } - - /// Is this an Apple tvOS triple. - public var isTvOS: Bool { - self == .tvos - } - - /// Is this an Apple watchOS triple. - public var isWatchOS: Bool { - self == .watchos - } - - /// isOSDarwin - Is this a "Darwin" OS (OS X, iOS, or watchOS). - public var isDarwin: Bool { - isMacOSX || isiOS || isWatchOS - } + public var isWindows: Bool { + self == .win32 + } + + public var isAIX: Bool { + self == .aix + } + + /// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both + /// "darwin" and "osx" as OS X triples. + public var isMacOSX: Bool { + self == .darwin || self == .macosx + } + + /// Is this an iOS triple. + /// Note: This identifies tvOS as a variant of iOS. If that ever + /// changes, i.e., if the two operating systems diverge or their version + /// numbers get out of sync, that will need to be changed. + /// watchOS has completely different version numbers so it is not included. + public var isiOS: Bool { + self == .ios || isTvOS + } + + /// Is this an Apple tvOS triple. + public var isTvOS: Bool { + self == .tvos + } + + /// Is this an Apple watchOS triple. + public var isWatchOS: Bool { + self == .watchos + } + + /// isOSDarwin - Is this a "Darwin" OS (OS X, iOS, or watchOS). + public var isDarwin: Bool { + isMacOSX || isiOS || isWatchOS + } } // MARK: - Versions extension Triple { - fileprivate func component(at i: Int) -> String { - let components = triple.split(separator: "-", maxSplits: 3, - omittingEmptySubsequences: false) - guard i < components.endIndex else { return "" } - return String(components[i]) - } - - public var archName: String { component(at: 0) } - public var vendorName: String { component(at: 1) } - - /// Returns the name of the OS from the triple string. - public var osName: String { component(at: 2) } - - public var environmentName: String { component(at: 3) } - - /// Parse the version number from the OS name component of the triple, if present. - /// - /// For example, "fooos1.2.3" would return (1, 2, 3). If an entry is not defined, it will - /// be returned as 0. - /// - /// This does not do any normalization of the version; for instance, a - /// `darwin` OS version number is not adjusted to match the equivalent - /// `macosx` version number. It's usually better to use `version(for:)` - /// to get Darwin versions. - public var osVersion: Version { - var osName = self.osName[...] - - // Assume that the OS portion of the triple starts with the canonical name. - if let os = os { - if osName.hasPrefix(os.name) { - osName = osName.dropFirst(os.name.count) - } else if os == .macosx, osName.hasPrefix("macos") { - osName = osName.dropFirst(5) - } + fileprivate func component(at i: Int) -> String { + let components = triple.split( + separator: "-", + maxSplits: 3, + omittingEmptySubsequences: false + ) + guard i < components.endIndex else { return "" } + return String(components[i]) } - return Version(parse: osName) - } + public var archName: String { component(at: 0) } + public var vendorName: String { component(at: 1) } + + /// Returns the name of the OS from the triple string. + public var osName: String { component(at: 2) } + + public var environmentName: String { component(at: 3) } + + /// Parse the version number from the OS name component of the triple, if present. + /// + /// For example, "fooos1.2.3" would return (1, 2, 3). If an entry is not defined, it will + /// be returned as 0. + /// + /// This does not do any normalization of the version; for instance, a + /// `darwin` OS version number is not adjusted to match the equivalent + /// `macosx` version number. It's usually better to use `version(for:)` + /// to get Darwin versions. + public var osVersion: Version { + var osName = self.osName[...] + + // Assume that the OS portion of the triple starts with the canonical name. + if let os = os { + if osName.hasPrefix(os.name) { + osName = osName.dropFirst(os.name.count) + } else if os == .macosx, osName.hasPrefix("macos") { + osName = osName.dropFirst(5) + } + } + + return Version(parse: osName) + } - public var osNameUnversioned: String { - var canonicalOsName = self.osName[...] + public var osNameUnversioned: String { + var canonicalOsName = self.osName[...] - // Assume that the OS portion of the triple starts with the canonical name. - if let os = os { - if canonicalOsName.hasPrefix(os.name) { - canonicalOsName = osName.prefix(os.name.count) - } else if os == .macosx, osName.hasPrefix("macos") { - canonicalOsName = osName.prefix(5) - } + // Assume that the OS portion of the triple starts with the canonical name. + if let os = os { + if canonicalOsName.hasPrefix(os.name) { + canonicalOsName = osName.prefix(os.name.count) + } else if os == .macosx, osName.hasPrefix("macos") { + canonicalOsName = osName.prefix(5) + } + } + return String(canonicalOsName) } - return String(canonicalOsName) - } } // MARK: - Darwin Versions extension Triple { - /// Parse the version number as with getOSVersion and then - /// translate generic "darwin" versions to the corresponding OS X versions. - /// This may also be called with IOS triples but the OS X version number is - /// just set to a constant 10.4.0 in that case. - /// - /// Returns true if successful. - /// - /// This accessor is semi-private; it's typically better to use `version(for:)` or - /// `Triple.FeatureAvailability`. - public var _macOSVersion: Version? { - var version = osVersion - - switch os { - case .darwin: - // Default to darwin8, i.e., MacOSX 10.4. - if version.major == 0 { - version.major = 8 - } - - // Darwin version numbers are skewed from OS X versions. - if version.major < 4 { - return nil - } - - if version.major <= 19 { - version.micro = 0 - version.minor = version.major - 4 - version.major = 10 - } else { - version.micro = 0 - version.minor = 0 - // darwin20+ corresponds to macOS 11+. - version.major = version.major - 9 - } - - case .macosx: - // Default to 10.4. - if version.major == 0 { - version.major = 10 - version.minor = 4 - } - - if version.major < 10 { - return nil - } - - case .ios, .tvos, .watchos: - // Ignore the version from the triple. This is only handled because the - // the clang driver combines OS X and IOS support into a common Darwin - // toolchain that wants to know the OS X version number even when targeting - // IOS. - version = Version(10, 4, 0) - - default: - fatalError("unexpected OS for Darwin triple") + /// Parse the version number as with getOSVersion and then + /// translate generic "darwin" versions to the corresponding OS X versions. + /// This may also be called with IOS triples but the OS X version number is + /// just set to a constant 10.4.0 in that case. + /// + /// Returns true if successful. + /// + /// This accessor is semi-private; it's typically better to use `version(for:)` or + /// `Triple.FeatureAvailability`. + public var _macOSVersion: Version? { + var version = osVersion + + switch os { + case .darwin: + // Default to darwin8, i.e., MacOSX 10.4. + if version.major == 0 { + version.major = 8 + } + + // Darwin version numbers are skewed from OS X versions. + if version.major < 4 { + return nil + } + + if version.major <= 19 { + version.micro = 0 + version.minor = version.major - 4 + version.major = 10 + } else { + version.micro = 0 + version.minor = 0 + // darwin20+ corresponds to macOS 11+. + version.major = version.major - 9 + } + + case .macosx: + // Default to 10.4. + if version.major == 0 { + version.major = 10 + version.minor = 4 + } + + if version.major < 10 { + return nil + } + + case .ios, .tvos, .watchos: + // Ignore the version from the triple. This is only handled because the + // the clang driver combines OS X and IOS support into a common Darwin + // toolchain that wants to know the OS X version number even when targeting + // IOS. + version = Version(10, 4, 0) + + default: + fatalError("unexpected OS for Darwin triple") + } + return version } - return version - } - - /// Parse the version number as with getOSVersion. This should - /// only be called with IOS or generic triples. - /// - /// This accessor is semi-private; it's typically better to use `version(for:)` or - /// `Triple.FeatureAvailability`. - public var _iOSVersion: Version { - switch os { - case .darwin, .macosx: - // Ignore the version from the triple. This is only handled because the - // the clang driver combines OS X and iOS support into a common Darwin - // toolchain that wants to know the iOS version number even when targeting - // OS X. - return Version(5, 0, 0) - case .ios, .tvos: - var version = self.osVersion - // Default to 5.0 (or 7.0 for arm64). - if version.major == 0 { - version.major = arch == .aarch64 ? 7 : 5 - } - return version - case .watchos: - fatalError("conflicting triple info") - default: - fatalError("unexpected OS for Darwin triple") + + /// Parse the version number as with getOSVersion. This should + /// only be called with IOS or generic triples. + /// + /// This accessor is semi-private; it's typically better to use `version(for:)` or + /// `Triple.FeatureAvailability`. + public var _iOSVersion: Version { + switch os { + case .darwin, .macosx: + // Ignore the version from the triple. This is only handled because the + // the clang driver combines OS X and iOS support into a common Darwin + // toolchain that wants to know the iOS version number even when targeting + // OS X. + return Version(5, 0, 0) + case .ios, .tvos: + var version = self.osVersion + // Default to 5.0 (or 7.0 for arm64). + if version.major == 0 { + version.major = arch == .aarch64 ? 7 : 5 + } + return version + case .watchos: + fatalError("conflicting triple info") + default: + fatalError("unexpected OS for Darwin triple") + } } - } - - /// Parse the version number as with getOSVersion. This should only be - /// called with WatchOS or generic triples. - /// - /// This accessor is semi-private; it's typically better to use `version(for:)` or - /// `Triple.FeatureAvailability`. - public var _watchOSVersion: Version { - switch os { - case .darwin, .macosx: - // Ignore the version from the triple. This is only handled because the - // the clang driver combines OS X and iOS support into a common Darwin - // toolchain that wants to know the iOS version number even when targeting - // OS X. - return Version(2, 0, 0) - case .watchos: - var version = self.osVersion - if version.major == 0 { - version.major = 2 - } - return version - case .ios: - fatalError("conflicting triple info") - default: - fatalError("unexpected OS for Darwin triple") + + /// Parse the version number as with getOSVersion. This should only be + /// called with WatchOS or generic triples. + /// + /// This accessor is semi-private; it's typically better to use `version(for:)` or + /// `Triple.FeatureAvailability`. + public var _watchOSVersion: Version { + switch os { + case .darwin, .macosx: + // Ignore the version from the triple. This is only handled because the + // the clang driver combines OS X and iOS support into a common Darwin + // toolchain that wants to know the iOS version number even when targeting + // OS X. + return Version(2, 0, 0) + case .watchos: + var version = self.osVersion + if version.major == 0 { + version.major = 2 + } + return version + case .ios: + fatalError("conflicting triple info") + default: + fatalError("unexpected OS for Darwin triple") + } } - } } // MARK: - Catalyst extension Triple { - @_spi(Testing) public var isMacCatalyst: Bool { - return self.isiOS && !self.isTvOS && environment == .macabi - } - - func isValidForZipperingWithTriple(_ variant: Triple) -> Bool { - guard archName == variant.archName, - arch == variant.arch, - subArch == variant.subArch, - vendor == variant.vendor else { - return false + @_spi(Testing) public var isMacCatalyst: Bool { + return self.isiOS && !self.isTvOS && environment == .macabi } - // Allow a macOS target and an iOS-macabi target variant - // This is typically the case when zippering a library originally - // developed for macOS. - if self.isMacOSX && variant.isMacCatalyst { - return true - } + func isValidForZipperingWithTriple(_ variant: Triple) -> Bool { + guard archName == variant.archName, + arch == variant.arch, + subArch == variant.subArch, + vendor == variant.vendor + else { + return false + } - // Allow an iOS-macabi target and a macOS target variant. This would - // be the case when zippering a library originally developed for - // iOS. - if variant.isMacOSX && isMacCatalyst { - return true - } + // Allow a macOS target and an iOS-macabi target variant + // This is typically the case when zippering a library originally + // developed for macOS. + if self.isMacOSX && variant.isMacCatalyst { + return true + } + + // Allow an iOS-macabi target and a macOS target variant. This would + // be the case when zippering a library originally developed for + // iOS. + if variant.isMacOSX && isMacCatalyst { + return true + } - return false - } + return false + } } fileprivate extension Array { - mutating func resize(toCount desiredCount: Int, paddingWith element: Element) { + mutating func resize(toCount desiredCount: Int, paddingWith element: Element) { - if desiredCount > count { - append(contentsOf: repeatElement(element, count: desiredCount - count)) - } else if desiredCount < count { - removeLast(count - desiredCount) + if desiredCount > count { + append(contentsOf: repeatElement(element, count: desiredCount - count)) + } else if desiredCount < count { + removeLast(count - desiredCount) + } } - } } diff --git a/Sources/BinarySymbols/ClangHostDefaultObjectsDetector.swift b/Sources/BinarySymbols/ClangHostDefaultObjectsDetector.swift index ef22c3968d6..18fa42003ce 100644 --- a/Sources/BinarySymbols/ClangHostDefaultObjectsDetector.swift +++ b/Sources/BinarySymbols/ClangHostDefaultObjectsDetector.swift @@ -14,7 +14,9 @@ import Foundation import protocol TSCBasic.WritableByteStream package func detectDefaultObjects( - clang: AbsolutePath, fileSystem: any FileSystem, hostTriple: Triple, + clang: AbsolutePath, + fileSystem: any FileSystem, + hostTriple: Triple, observabilityScope: ObservabilityScope ) async throws -> [AbsolutePath] { let clangProcess = AsyncProcess(args: clang.pathString, "-###", "-x", "c", "-") @@ -97,7 +99,8 @@ package func detectDefaultObjects( // First try and locate the file relative to the linker script. let siblingPath = try AbsolutePath( validating: arg, - relativeTo: try AbsolutePath(validating: library.dirname)) + relativeTo: try AbsolutePath(validating: library.dirname) + ) if fileSystem.isFile(siblingPath) { try handleArgument(siblingPath.pathString) } else { diff --git a/Sources/BinarySymbols/LLVMObjdumpSymbolProvider.swift b/Sources/BinarySymbols/LLVMObjdumpSymbolProvider.swift index 70db3c39e82..4f03e20c3f5 100644 --- a/Sources/BinarySymbols/LLVMObjdumpSymbolProvider.swift +++ b/Sources/BinarySymbols/LLVMObjdumpSymbolProvider.swift @@ -23,7 +23,8 @@ package struct LLVMObjdumpSymbolProvider: SymbolProvider { try objdumpProcess.launch() let result = try await objdumpProcess.waitUntilExit() guard case .terminated(let status) = result.exitStatus, - status == 0 else { + status == 0 + else { throw InternalError("Unable to run llvm-objdump") } @@ -37,7 +38,7 @@ package struct LLVMObjdumpSymbolProvider: SymbolProvider { let name = Reference() let symbolLineRegex = Regex { Anchor.startOfLine - Repeat(CharacterClass.hexDigit, count: 16) // The address of the symbol + Repeat(CharacterClass.hexDigit, count: 16) // The address of the symbol CharacterClass.whitespace Capture(as: visibility) { ChoiceOf { @@ -48,7 +49,7 @@ package struct LLVMObjdumpSymbolProvider: SymbolProvider { " " } } - Capture(as: weakLinkage) { // Whether the symbol is weak or strong + Capture(as: weakLinkage) { // Whether the symbol is weak or strong ChoiceOf { "w" " " @@ -78,10 +79,10 @@ package struct LLVMObjdumpSymbolProvider: SymbolProvider { "O" " " } - OneOrMore{ + OneOrMore { .whitespace } - Capture(as: section) { // The section the symbol appears in + Capture(as: section) { // The section the symbol appears in ZeroOrMore { .whitespace.inverted } @@ -90,7 +91,7 @@ package struct LLVMObjdumpSymbolProvider: SymbolProvider { .anyNonNewline } CharacterClass.whitespace - Capture(as: name) { // The name of symbol + Capture(as: name) { // The name of symbol OneOrMore { .whitespace.inverted } @@ -134,4 +135,3 @@ package struct LLVMObjdumpSymbolProvider: SymbolProvider { return line[sectionStart.. [String] { // Pass the path to the current module's module map if present. if let moduleMap = self.moduleMap { diff --git a/Sources/Build/BuildDescription/ProductBuildDescription.swift b/Sources/Build/BuildDescription/ProductBuildDescription.swift index 5c91a7c11d6..cdd2e1075e0 100644 --- a/Sources/Build/BuildDescription/ProductBuildDescription.swift +++ b/Sources/Build/BuildDescription/ProductBuildDescription.swift @@ -13,8 +13,7 @@ import Basics import PackageGraph -@_spi(SwiftPMInternal) -import PackageModel +@_spi(SwiftPMInternal) import PackageModel import OrderedCollections import SPMBuildCore @@ -180,9 +179,9 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription switch self.product.type { case .macro: #if BUILD_MACROS_AS_DYLIBS - derivedProductType = .library(.dynamic) + derivedProductType = .library(.dynamic) #else - derivedProductType = .executable + derivedProductType = .executable #endif default: derivedProductType = self.product.type @@ -200,7 +199,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription switch derivedProductType { case .macro: - throw InternalError("macro not supported") // should never be reached + throw InternalError("macro not supported") // should never be reached case .library(.automatic): throw InternalError("automatic library not supported") case .library(.static): @@ -245,7 +244,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription // Support for linking tests against executables is conditional on the tools // version of the package that defines the executable product. let executableTarget = try product.executableModule - if let target = executableTarget.underlying as? SwiftModule, + if let target = executableTarget.underlying as? SwiftModule, self.toolsVersion >= .v5_5, self.buildParameters.driverParameters.canRenameEntrypointFunctionName, target.supportsTestableExecutablesFeature @@ -290,13 +289,13 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription var strictMemorySafety = false for target in self.product.modules { let swiftSettings = target.underlying.buildSettingsDescription.filter { $0.tool == .swift } - for kind in swiftSettings.map(\.kind) { - if case let .enableExperimentalFeature(feature) = kind { - experimentalFeatures.append(feature) - } else if kind == .strictMemorySafety { - strictMemorySafety = true + for kind in swiftSettings.map(\.kind) { + if case let .enableExperimentalFeature(feature) = kind { + experimentalFeatures.append(feature) + } else if kind == .strictMemorySafety { + strictMemorySafety = true + } } - } } for feature in experimentalFeatures { @@ -393,9 +392,9 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription // Library search path for the toolchain's copy of SwiftSyntax. #if BUILD_MACROS_AS_DYLIBS - if product.type == .macro { - args += try ["-L", defaultBuildParameters.toolchain.hostLibDir.pathString] - } + if product.type == .macro { + args += try ["-L", defaultBuildParameters.toolchain.hostLibDir.pathString] + } #endif return self.stripInvalidArguments(args) @@ -406,16 +405,20 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription var flags: [String] = [] // Linked libraries. - let libraries = OrderedSet(self.staticTargets.reduce([]) { - $0 + self.buildParameters.createScope(for: $1).evaluate(.LINK_LIBRARIES) - }) + let libraries = OrderedSet( + self.staticTargets.reduce([]) { + $0 + self.buildParameters.createScope(for: $1).evaluate(.LINK_LIBRARIES) + } + ) flags += libraries.map { "-l" + $0 } // Linked frameworks. if self.buildParameters.triple.supportsFrameworks { - let frameworks = OrderedSet(self.staticTargets.reduce([]) { - $0 + self.buildParameters.createScope(for: $1).evaluate(.LINK_FRAMEWORKS) - }) + let frameworks = OrderedSet( + self.staticTargets.reduce([]) { + $0 + self.buildParameters.createScope(for: $1).evaluate(.LINK_FRAMEWORKS) + } + ) flags += frameworks.flatMap { ["-framework", $0] } } @@ -445,7 +448,7 @@ extension ProductBuildDescription: Identifiable { } extension SortedArray where Element == AbsolutePath { - public static func +=(lhs: inout SortedArray, rhs: S) where S.Iterator.Element == AbsolutePath { + public static func += (lhs: inout SortedArray, rhs: S) where S.Iterator.Element == AbsolutePath { lhs.insert(contentsOf: rhs) } } diff --git a/Sources/Build/BuildDescription/SwiftModuleBuildDescription.swift b/Sources/Build/BuildDescription/SwiftModuleBuildDescription.swift index 9a59bf3fff2..6d9738479b9 100644 --- a/Sources/Build/BuildDescription/SwiftModuleBuildDescription.swift +++ b/Sources/Build/BuildDescription/SwiftModuleBuildDescription.swift @@ -17,16 +17,14 @@ import PackageGraph import PackageLoading import TSCUtility -@_spi(SwiftPMInternal) -import PackageModel +@_spi(SwiftPMInternal) import PackageModel -@_spi(SwiftPMInternal) -import SPMBuildCore +@_spi(SwiftPMInternal) import SPMBuildCore #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import DriverSupport + @_implementationOnly import DriverSupport #else -import DriverSupport + import DriverSupport #endif import struct TSCBasic.ByteString @@ -123,7 +121,8 @@ public final class SwiftModuleBuildDescription { /// depending on the build parameters used. public var objects: [AbsolutePath] { get throws { - let relativeSources = self.target.sources.relativePaths + let relativeSources = + self.target.sources.relativePaths + self.derivedSources.relativePaths + self.pluginDerivedSources.relativePaths let ltoEnabled = self.buildParameters.linkingParameters.linkTimeOptimizationMode != nil @@ -131,7 +130,8 @@ public final class SwiftModuleBuildDescription { return try relativeSources.map { try AbsolutePath( validating: "\($0.basename).\(objectFileExtension)", - relativeTo: self.tempsPath) + relativeTo: self.tempsPath + ) } } } @@ -142,7 +142,7 @@ public final class SwiftModuleBuildDescription { } /// The path to the swiftmodule file after compilation. - public var moduleOutputPath: AbsolutePath { // note: needs to be public because of sourcekit-lsp + public var moduleOutputPath: AbsolutePath { // note: needs to be public because of sourcekit-lsp // If we're an executable and we're not allowing test targets to link against us, we hide the module. let triple = buildParameters.triple let allowLinkingAgainstExecutables = [.coff, .macho, .elf].contains(triple.objectFormat) && self.toolsVersion >= .v5_5 @@ -347,8 +347,7 @@ public final class SwiftModuleBuildDescription { } guard - self.buildParameters.triple.isDarwin() && - self.buildParameters.testingParameters.experimentalTestOutput + self.buildParameters.triple.isDarwin() && self.buildParameters.testingParameters.experimentalTestOutput else { return } @@ -423,18 +422,18 @@ public final class SwiftModuleBuildDescription { var args = [String]() #if BUILD_MACROS_AS_DYLIBS - try self.requiredMacros.forEach { macro in - args += [ - "-Xfrontend", "-load-plugin-library", - "-Xfrontend", macroBuildParameters.macroBinaryPath(macro).pathString - ] - } + try self.requiredMacros.forEach { macro in + args += [ + "-Xfrontend", "-load-plugin-library", + "-Xfrontend", macroBuildParameters.macroBinaryPath(macro).pathString, + ] + } #else - let macroModules = try self.requiredMacros - try macroModules.forEach { macro in - let executablePath = try macroBuildParameters.macroBinaryPath(macro).pathString - args += ["-Xfrontend", "-load-plugin-executable", "-Xfrontend", "\(executablePath)#\(macro.c99name)"] - } + let macroModules = try self.requiredMacros + try macroModules.forEach { macro in + let executablePath = try macroBuildParameters.macroBinaryPath(macro).pathString + args += ["-Xfrontend", "-load-plugin-executable", "-Xfrontend", "\(executablePath)#\(macro.c99name)"] + } #endif if self.shouldDisableSandbox { @@ -507,7 +506,7 @@ public final class SwiftModuleBuildDescription { // No `-` for these flags because the set of Strings in driver.supportedFrontendFlags do // not have a leading `-` if self.buildParameters.driverParameters.canRenameEntrypointFunctionName, - self.buildParameters.linkerFlagsForRenamingMainFunction(of: self.target) != nil + self.buildParameters.linkerFlagsForRenamingMainFunction(of: self.target) != nil { args += ["-Xfrontend", "-entry-point-function-name", "-Xfrontend", "\(self.target.c99name)_main"] } @@ -544,7 +543,8 @@ public final class SwiftModuleBuildDescription { } args += try self.cxxInteroperabilityModeArguments( - propagateFromCurrentModuleOtherSwiftFlags: false) + propagateFromCurrentModuleOtherSwiftFlags: false + ) // Add arguments from declared build settings. args += try self.buildSettingsFlags() @@ -559,7 +559,7 @@ public final class SwiftModuleBuildDescription { case .off: break case .on: - args += ["-Xfrontend", "-experimental-lazy-typecheck",] + args += ["-Xfrontend", "-experimental-lazy-typecheck"] if !args.contains("-enable-testing") { // enable-testing needs the non-exportable-decls args += ["-Xfrontend", "-experimental-skip-non-exportable-decls"] @@ -569,7 +569,7 @@ public final class SwiftModuleBuildDescription { args += [ "-Xfrontend", "-experimental-skip-all-function-bodies", "-Xfrontend", "-experimental-allow-module-with-compiler-errors", - "-Xfrontend", "-empty-abi-descriptor" + "-Xfrontend", "-empty-abi-descriptor", ] } @@ -628,11 +628,8 @@ public final class SwiftModuleBuildDescription { } // Pass `-user-module-version` for versioned packages that aren't pre-releases. - if - let version = package.manifest.version, - version.prereleaseIdentifiers.isEmpty && - version.buildMetadataIdentifiers.isEmpty && - toolsVersion >= .v6_0 + if let version = package.manifest.version, + version.prereleaseIdentifiers.isEmpty && version.buildMetadataIdentifiers.isEmpty && toolsVersion >= .v6_0 { args += ["-user-module-version", version.description] } @@ -667,7 +664,8 @@ public final class SwiftModuleBuildDescription { args += ["-module-cache-path", try self.buildParameters.moduleCache.pathString] args += try self.cxxInteroperabilityModeArguments( - propagateFromCurrentModuleOtherSwiftFlags: true) + propagateFromCurrentModuleOtherSwiftFlags: true + ) args += self.buildParameters.toolchain.extraFlags.swiftCompilerFlags @@ -827,7 +825,6 @@ public final class SwiftModuleBuildDescription { """# - // Write out the entries for each source file. let sources = self.sources let objects = try self.objects @@ -943,9 +940,9 @@ public final class SwiftModuleBuildDescription { // Include path for the toolchain's copy of SwiftSyntax. #if BUILD_MACROS_AS_DYLIBS - if module.type == .macro { - flags += try ["-I", self.defaultBuildParameters.toolchain.hostLibDir.pathString] - } + if module.type == .macro { + flags += try ["-I", self.defaultBuildParameters.toolchain.hostLibDir.pathString] + } #endif return flags @@ -1012,7 +1009,8 @@ public final class SwiftModuleBuildDescription { private var stdlibArguments: [String] { var arguments: [String] = [] - let isLinkingStaticStdlib = self.buildParameters.linkingParameters.shouldLinkStaticSwiftStdlib + let isLinkingStaticStdlib = + self.buildParameters.linkingParameters.shouldLinkStaticSwiftStdlib && self.buildParameters.triple.isSupportingStaticStdlib if isLinkingStaticStdlib { arguments += ["-static-stdlib"] @@ -1043,7 +1041,7 @@ public final class SwiftModuleBuildDescription { let toolchainFlags = self.buildParameters.toolchain.extraFlags.swiftCompilerFlags if toolchainFlags.contains(queryFlags) { return true } - + let generalFlags = self.buildParameters.flags.swiftCompilerFlags if generalFlags.contains(queryFlags) { return true } diff --git a/Sources/Build/BuildManifest/LLBuildManifestBuilder+Product.swift b/Sources/Build/BuildManifest/LLBuildManifestBuilder+Product.swift index 33eb6f4558f..5a6c9011176 100644 --- a/Sources/Build/BuildManifest/LLBuildManifestBuilder+Product.swift +++ b/Sources/Build/BuildManifest/LLBuildManifestBuilder+Product.swift @@ -27,7 +27,8 @@ extension LLBuildManifestBuilder { let testInputs: [AbsolutePath] if buildProduct.product.type == .test && buildProduct.buildParameters.triple.isDarwin() - && buildProduct.buildParameters.testingParameters.experimentalTestOutput { + && buildProduct.buildParameters.testingParameters.experimentalTestOutput + { let testBundleInfoPlistPath = try buildProduct.binaryPath.parentDirectory.parentDirectory.appending(component: "Info.plist") testInputs = [testBundleInfoPlistPath] @@ -56,7 +57,8 @@ extension LLBuildManifestBuilder { ) default: - let inputs = try buildProduct.objects + let inputs = + try buildProduct.objects + buildProduct.dylibs.map { try $0.binaryPath } + [buildProduct.linkFileListPath] + testInputs @@ -65,8 +67,9 @@ extension LLBuildManifestBuilder { let linkedBinaryNode: Node let linkedBinaryPath = try buildProduct.binaryPath if case .executable = buildProduct.product.type, - buildProduct.buildParameters.triple.isMacOSX, - buildProduct.buildParameters.debuggingParameters.shouldEnableDebuggingEntitlement { + buildProduct.buildParameters.triple.isMacOSX, + buildProduct.buildParameters.debuggingParameters.shouldEnableDebuggingEntitlement + { shouldCodeSign = true linkedBinaryNode = try .file(buildProduct.binaryPath, isMutated: true) } else { @@ -182,9 +185,9 @@ func getLLBuildTargetName( ) -> String { assert(macro.type == .macro) #if BUILD_MACROS_AS_DYLIBS - return dynamicLibraryName(for: macro.name, buildParameters: buildParameters) + return dynamicLibraryName(for: macro.name, buildParameters: buildParameters) #else - return executableName(for: macro.name, buildParameters: buildParameters) + return executableName(for: macro.name, buildParameters: buildParameters) #endif } diff --git a/Sources/Build/BuildManifest/LLBuildManifestBuilder+Swift.swift b/Sources/Build/BuildManifest/LLBuildManifestBuilder+Swift.swift index 0616405e89b..026f8470dee 100644 --- a/Sources/Build/BuildManifest/LLBuildManifestBuilder+Swift.swift +++ b/Sources/Build/BuildManifest/LLBuildManifestBuilder+Swift.swift @@ -23,15 +23,15 @@ import func TSCBasic.topologicalSort import struct Basics.Environment #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import class DriverSupport.SPMSwiftDriverExecutor -@_implementationOnly import Foundation -@_implementationOnly import SwiftDriver -@_implementationOnly import TSCUtility + @_implementationOnly import class DriverSupport.SPMSwiftDriverExecutor + @_implementationOnly import Foundation + @_implementationOnly import SwiftDriver + @_implementationOnly import TSCUtility #else -import class DriverSupport.SPMSwiftDriverExecutor -import Foundation -import SwiftDriver -import TSCUtility + import class DriverSupport.SPMSwiftDriverExecutor + import Foundation + import SwiftDriver + import TSCUtility #endif import PackageModel @@ -233,9 +233,7 @@ extension LLBuildManifestBuilder { // and their products to speed up search here, which is inefficient if the plan // contains a lot of products. if let productDescription = try plan.productMap.values.first(where: { - try $0.product.type == .executable && - $0.product.executableModule.id == module.id && - $0.destination == description.destination + try $0.product.type == .executable && $0.product.executableModule.id == module.id && $0.destination == description.destination }) { try inputs.append(file: productDescription.binaryPath) } @@ -303,10 +301,14 @@ extension LLBuildManifestBuilder { // Depend on any required macro's output. try target.requiredMacros.forEach { macro in - inputs.append(.virtual(getLLBuildTargetName( - macro: macro, - buildParameters: target.macroBuildParameters - ))) + inputs.append( + .virtual( + getLLBuildTargetName( + macro: macro, + buildParameters: target.macroBuildParameters + ) + ) + ) } return inputs + additionalInputs @@ -390,7 +392,8 @@ extension Driver { func checkLDPathOption(commandLine: [String]) throws { // `-ld-path` option is only available in recent versions of the compiler: rdar://117049947 if let option = commandLine.first(where: { $0.hasPrefix("-ld-path") }), - !self.supportedFrontendFeatures.contains("ld-path-driver-option") { + !self.supportedFrontendFeatures.contains("ld-path-driver-option") + { throw LLBuildManifestBuilder.Error.ldPathDriverOptionUnavailable(option: option) } } diff --git a/Sources/Build/BuildManifest/LLBuildManifestBuilder.swift b/Sources/Build/BuildManifest/LLBuildManifestBuilder.swift index a8d7ef2126e..99f4a5eb124 100644 --- a/Sources/Build/BuildManifest/LLBuildManifestBuilder.swift +++ b/Sources/Build/BuildManifest/LLBuildManifestBuilder.swift @@ -17,9 +17,9 @@ import PackageModel import SPMBuildCore #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import SwiftDriver + @_implementationOnly import SwiftDriver #else -import SwiftDriver + import SwiftDriver #endif import struct TSCBasic.ByteString @@ -256,8 +256,9 @@ extension LLBuildManifestBuilder { private func addTestEntryPointGenerationCommand() throws { for module in self.plan.targets { guard case .swift(let swiftModule) = module, - case .entryPoint(let isSynthesized) = swiftModule.testTargetRole, - isSynthesized else { continue } + case .entryPoint(let isSynthesized) = swiftModule.testTargetRole, + isSynthesized + else { continue } let testEntryPointTarget = swiftModule @@ -297,7 +298,8 @@ extension ModuleBuildDescription { /// then this returns that Swift target build description, else returns nil. fileprivate var testDiscoveryTargetBuildDescription: SwiftModuleBuildDescription? { guard case .swift(let targetBuildDescription) = self, - case .discovery = targetBuildDescription.testTargetRole else { return nil } + case .discovery = targetBuildDescription.testTargetRole + else { return nil } return targetBuildDescription } } diff --git a/Sources/Build/BuildOperation.swift b/Sources/Build/BuildOperation.swift index ee3b48adfb6..6ac15abd5c9 100644 --- a/Sources/Build/BuildOperation.swift +++ b/Sources/Build/BuildOperation.swift @@ -11,8 +11,7 @@ //===----------------------------------------------------------------------===// import _Concurrency -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import Foundation import LLBuildManifest import PackageGraph @@ -29,11 +28,11 @@ import struct TSCBasic.RegEx import enum TSCUtility.Diagnostics #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import DriverSupport -@_implementationOnly import SwiftDriver + @_implementationOnly import DriverSupport + @_implementationOnly import SwiftDriver #else -import DriverSupport -import SwiftDriver + import DriverSupport + import SwiftDriver #endif package struct LLBuildSystemConfiguration { @@ -337,11 +336,13 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS return } // Ensure the compiler supports the import-scan operation - guard DriverSupport.checkSupportedFrontendFlags( - flags: ["import-prescan"], - toolchain: self.config.toolchain(for: .target), - fileSystem: localFileSystem - ) else { + guard + DriverSupport.checkSupportedFrontendFlags( + flags: ["import-prescan"], + toolchain: self.config.toolchain(for: .target), + fileSystem: localFileSystem + ) + else { return } @@ -353,21 +354,26 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS } let targetDependenciesSet = Set(dependencies) guard !description.generatedSourceTargetSet.contains(target), - targetDependenciesSet.intersection(description.generatedSourceTargetSet).isEmpty else { + targetDependenciesSet.intersection(description.generatedSourceTargetSet).isEmpty + else { // Skip targets which contain, or depend-on-targets, with generated source-code. // Such as test discovery targets and targets with plugins. continue } let resolver = try ArgsResolver(fileSystem: localFileSystem) - let executor = SPMSwiftDriverExecutor(resolver: resolver, - fileSystem: localFileSystem, - env: Environment.current) + let executor = SPMSwiftDriverExecutor( + resolver: resolver, + fileSystem: localFileSystem, + env: Environment.current + ) let consumeDiagnostics: DiagnosticsEngine = DiagnosticsEngine(handlers: []) - var driver = try Driver(args: commandLine, - diagnosticsOutput: .engine(consumeDiagnostics), - fileSystem: localFileSystem, - executor: executor) + var driver = try Driver( + args: commandLine, + diagnosticsOutput: .engine(consumeDiagnostics), + fileSystem: localFileSystem, + executor: executor + ) guard !consumeDiagnostics.hasErrors else { // If we could not init the driver with this command, something went wrong, // proceed without checking this target. @@ -379,12 +385,12 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS let importedTargetsMissingDependency = Set(imports).intersection(nonDependencyTargetsSet) if let missedDependency = importedTargetsMissingDependency.first { switch checkingMode { - case .error: - self.observabilityScope.emit(error: "Target \(target) imports another target (\(missedDependency)) in the package without declaring it a dependency.") - case .warn: - self.observabilityScope.emit(warning: "Target \(target) imports another target (\(missedDependency)) in the package without declaring it a dependency.") - case .none: - fatalError("Explicit import checking is disabled.") + case .error: + self.observabilityScope.emit(error: "Target \(target) imports another target (\(missedDependency)) in the package without declaring it a dependency.") + case .warn: + self.observabilityScope.emit(warning: "Target \(target) imports another target (\(missedDependency)) in the package without declaring it a dependency.") + case .none: + fatalError("Explicit import checking is disabled.") } } } catch { @@ -469,12 +475,15 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS case .library(let kind): let artifactKind: PluginInvocationBuildResult.BuiltArtifact.Kind switch kind { - case .dynamic: artifactKind = .dynamicLibrary - case .static, .automatic: artifactKind = .staticLibrary + case .dynamic: artifactKind = .dynamicLibrary + case .static, .automatic: artifactKind = .staticLibrary } - return try ($0.product.name, .init( - path: $0.binaryPath.pathString, - kind: artifactKind) + return try ( + $0.product.name, + .init( + path: $0.binaryPath.pathString, + kind: artifactKind + ) ) case .executable: return try ($0.product.name, .init(path: $0.binaryPath.pathString, kind: .executable)) @@ -508,8 +517,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS component: configuration.dirname ) if self.fileSystem.exists(oldBuildPath) { - do { try self.fileSystem.removeFileTree(oldBuildPath) } - catch { + do { try self.fileSystem.removeFileTree(oldBuildPath) } catch { self.observabilityScope.emit( warning: "unable to delete \(oldBuildPath), skip creating symbolic link", underlyingError: error @@ -550,10 +558,10 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS pluginsToCompile = allPlugins continueBuilding = true case .product(let productName, _): - pluginsToCompile = allPlugins.filter{ $0.productNames.contains(productName) } + pluginsToCompile = allPlugins.filter { $0.productNames.contains(productName) } continueBuilding = pluginsToCompile.isEmpty case .target(let targetName, _): - pluginsToCompile = allPlugins.filter{ $0.moduleName == targetName } + pluginsToCompile = allPlugins.filter { $0.moduleName == targetName } continueBuilding = pluginsToCompile.isEmpty } @@ -666,15 +674,16 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS throw Diagnostics.fatalError } - let buildParameters = if let destination { - config.buildParameters(for: destination) - } else if product.type == .macro || product.type == .plugin { - config.buildParameters(for: .host) - } else if product.type == .test { - config.buildParameters(for: product.hasDirectMacroDependencies ? .host : .target) - } else { - config.buildParameters(for: .target) - } + let buildParameters = + if let destination { + config.buildParameters(for: destination) + } else if product.type == .macro || product.type == .plugin { + config.buildParameters(for: .host) + } else if product.type == .test { + config.buildParameters(for: product.hasDirectMacroDependencies ? .host : .target) + } else { + config.buildParameters(for: .target) + } // If the product is automatic, we build the main target because automatic products // do not produce a binary right now. @@ -697,15 +706,16 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS throw Diagnostics.fatalError } - let buildParameters = if let destination { - config.buildParameters(for: destination) - } else if module.type == .macro || module.type == .plugin { - config.buildParameters(for: .host) - } else if module.type == .test { - try config.buildParameters(for: inferTestDestination(testModule: module, graph: graph)) - } else { - config.buildParameters(for: .target) - } + let buildParameters = + if let destination { + config.buildParameters(for: destination) + } else if module.type == .macro || module.type == .plugin { + config.buildParameters(for: .host) + } else if module.type == .test { + try config.buildParameters(for: inferTestDestination(testModule: module, graph: graph)) + } else { + config.buildParameters(for: .target) + } return module.getLLBuildTargetName(buildParameters: buildParameters) } @@ -756,8 +766,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS // Emit warnings about any unhandled files in authored packages. We do this after applying build tool plugins, once we know what files they handled. // rdar://113256834 This fix works for the plugins that do not have PreBuildCommands. let targetsToConsider: [ResolvedModule] - if let subset = subset, let recursiveDependencies = try - subset.recursiveDependencies(for: plan.graph, observabilityScope: observabilityScope) { + if let subset = subset, let recursiveDependencies = try subset.recursiveDependencies(for: plan.graph, observabilityScope: observabilityScope) { targetsToConsider = recursiveDependencies } else { targetsToConsider = Array(plan.graph.reachableModules) @@ -792,7 +801,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS buildToolPluginInvocationResults: [BuildToolPluginInvocationResult] ) { guard let package = modulesGraph.package(for: module), - package.manifest.toolsVersion >= .v5_3 + package.manifest.toolsVersion >= .v5_3 else { return } @@ -919,11 +928,9 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS public func packageStructureChanged() async -> Bool { do { _ = try await self.generateDescription() - } - catch Diagnostics.fatalError { + } catch Diagnostics.fatalError { return false - } - catch { + } catch { self.observabilityScope.emit(error) return false } @@ -967,7 +974,8 @@ extension BuildOperation { var config = self.config config.manifestPath = config.dataPath(for: .host).appending( - components: "..", "plugin-tools.yaml" + components: "..", + "plugin-tools.yaml" ) // FIXME: It should be possible to share database between plugin tools diff --git a/Sources/Build/BuildPlan/BuildPlan+Product.swift b/Sources/Build/BuildPlan/BuildPlan+Product.swift index b290f9e3fd3..688025a5d47 100644 --- a/Sources/Build/BuildPlan/BuildPlan+Product.swift +++ b/Sources/Build/BuildPlan/BuildPlan+Product.swift @@ -19,8 +19,7 @@ import struct PackageGraph.ResolvedProduct import class PackageModel.BinaryModule import class PackageModel.ClangModule -@_spi(SwiftPMInternal) -import class PackageModel.Module +@_spi(SwiftPMInternal) import class PackageModel.Module import class PackageModel.SwiftModule import class PackageModel.SystemLibraryModule @@ -130,18 +129,19 @@ extension BuildPlan { // For test targets, we need to consider the first level of transitive dependencies since the first level is // always test targets. - let topLevelDependencies: [PackageModel.Module] = if product.type == .test { - product.modules.flatMap(\.underlying.dependencies).compactMap { - switch $0 { - case .product: - nil - case .module(let target, _): - target + let topLevelDependencies: [PackageModel.Module] = + if product.type == .test { + product.modules.flatMap(\.underlying.dependencies).compactMap { + switch $0 { + case .product: + nil + case .module(let target, _): + target + } } + } else { + [] } - } else { - [] - } // get the dynamic libraries for explicitly linking rdar://108561857 func recursiveDynamicLibraries(for description: ProductBuildDescription) throws -> [ProductBuildDescription] { @@ -170,10 +170,12 @@ extension BuildPlan { guard let description = self.description(for: product, context: destination) else { throw InternalError("Could not find a description for product: \(product)") } - return try recursiveDynamicLibraries(for: description).map { TraversalNode( - product: $0.product, - context: $0.destination - ) } + return try recursiveDynamicLibraries(for: description).map { + TraversalNode( + product: $0.product, + context: $0.destination + ) + } case .test, .executable, .snippet, .macro: return [] } @@ -183,8 +185,10 @@ extension BuildPlan { for module: ResolvedModule, destination: BuildParameters.Destination ) -> [TraversalNode] { - let isTopLevel = topLevelDependencies.contains(module.underlying) || product.modules - .contains(id: module.id) + let isTopLevel = + topLevelDependencies.contains(module.underlying) + || product.modules + .contains(id: module.id) let topLevelIsMacro = isTopLevel && product.type == .macro let topLevelIsPlugin = isTopLevel && product.type == .plugin let topLevelIsTest = isTopLevel && product.type == .test @@ -212,14 +216,15 @@ extension BuildPlan { var uniqueNodes = Set(directDependencies) try depthFirstSearch(directDependencies) { - let result: [TraversalNode] = switch $0 { - case .product(let product, let destination): - try successors(for: product, destination: destination) - case .module(let module, let destination): - successors(for: module, destination: destination) - case .package: - [] - } + let result: [TraversalNode] = + switch $0 { + case .product(let product, let destination): + try successors(for: product, destination: destination) + case .module(let module, let destination): + successors(for: module, destination: destination) + case .package: + [] + } return result.filter { uniqueNodes.insert($0).inserted } } onNext: { node, _ in @@ -255,14 +260,17 @@ extension BuildPlan { throw InternalError("Could not find a description for module: \(module)") } staticTargets.append(description) - } else if product.type == .test && (module.underlying as? SwiftModule)? - .supportsTestableExecutablesFeature == true + } else if product.type == .test + && (module.underlying as? SwiftModule)? + .supportsTestableExecutablesFeature == true { // Only "top-level" targets should really be considered here, not transitive ones. - let isTopLevel = topLevelDependencies.contains(module.underlying) || product.modules - .contains(id: module.id) + let isTopLevel = + topLevelDependencies.contains(module.underlying) + || product.modules + .contains(id: module.id) if let toolsVersion = graph.package(for: product)?.manifest.toolsVersion, toolsVersion >= .v5_5, - isTopLevel + isTopLevel { guard let description else { throw InternalError("Could not find a description for module: \(module)") @@ -306,12 +314,13 @@ extension BuildPlan { } case .artifactsArchive: let tools = try self.parseExecutableArtifactsArchive( - for: binaryTarget, triple: productDescription.buildParameters.triple + for: binaryTarget, + triple: productDescription.buildParameters.triple ) for tool in tools { availableTools[tool.name] = tool.executablePath } - + let libraries = try self.parseLibraryArtifactsArchive( for: binaryTarget, triple: productDescription.buildParameters.triple @@ -339,9 +348,11 @@ extension BuildPlan { // Add derived test targets, if necessary if product.type == .test, let derivedTestTargets = derivedTestTargetsMap[product.id] { - staticTargets.append(contentsOf: derivedTestTargets.compactMap { - self.description(for: $0, context: productDescription.destination) - }) + staticTargets.append( + contentsOf: derivedTestTargets.compactMap { + self.description(for: $0, context: productDescription.destination) + } + ) } return (linkLibraries, staticTargets, systemModules, libraryBinaryPaths, availableTools) diff --git a/Sources/Build/BuildPlan/BuildPlan+Test.swift b/Sources/Build/BuildPlan/BuildPlan+Test.swift index 545ecb2702f..949f9dd16c7 100644 --- a/Sources/Build/BuildPlan/BuildPlan+Test.swift +++ b/Sources/Build/BuildPlan/BuildPlan+Test.swift @@ -17,14 +17,11 @@ import struct LLBuildManifest.TestDiscoveryTool import struct LLBuildManifest.TestEntryPointTool import struct PackageGraph.ModulesGraph -@_spi(SwiftPMInternal) -import struct PackageGraph.ResolvedPackage +@_spi(SwiftPMInternal) import struct PackageGraph.ResolvedPackage -@_spi(SwiftPMInternal) -import struct PackageGraph.ResolvedProduct +@_spi(SwiftPMInternal) import struct PackageGraph.ResolvedProduct -@_spi(SwiftPMInternal) -import struct PackageGraph.ResolvedModule +@_spi(SwiftPMInternal) import struct PackageGraph.ResolvedModule import struct PackageModel.Sources import enum PackageModel.BuildSettings @@ -100,7 +97,7 @@ extension BuildPlan { let discoveryTarget = SwiftModule( name: discoveryTargetName, dependencies: testProduct.underlying.modules.map { .module($0, conditions: []) }, - packageAccess: true, // test target is allowed access to package decls by default + packageAccess: true, // test target is allowed access to package decls by default testDiscoverySrc: Sources(paths: discoveryPaths, root: discoveryDerivedDir), buildSettings: discoveryBuildSettings, implicit: true @@ -157,7 +154,7 @@ extension BuildPlan { name: testProduct.name, type: .library, dependencies: testProduct.underlying.modules.map { .module($0, conditions: []) } + swiftTargetDependencies, - packageAccess: true, // test target is allowed access to package decls + packageAccess: true, // test target is allowed access to package decls testEntryPointSources: entryPointSources, buildSettings: entryPointBuildSettings ) diff --git a/Sources/Build/BuildPlan/BuildPlan.swift b/Sources/Build/BuildPlan/BuildPlan.swift index bef12b95fa8..cdc2c151466 100644 --- a/Sources/Build/BuildPlan/BuildPlan.swift +++ b/Sources/Build/BuildPlan/BuildPlan.swift @@ -22,9 +22,9 @@ import SPMBuildCore import TSCBasic #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import SwiftDriver + @_implementationOnly import SwiftDriver #else -import SwiftDriver + import SwiftDriver #endif import enum TSCUtility.Diagnostics @@ -149,9 +149,9 @@ public class BuildPlan: SPMBuildCore.BuildPlan { switch self { case .noBuildableTarget: return """ - The package does not contain a buildable target. - Add at least one `.target` or `.executableTarget` to your `Package.swift`. - """ + The package does not contain a buildable target. + Add at least one `.target` or `.executableTarget` to your `Package.swift`. + """ } } } @@ -280,14 +280,16 @@ public class BuildPlan: SPMBuildCore.BuildPlan { throw InternalError("Package not found for product: \(product.name)") } - try productMap.insert(ProductBuildDescription( - package: package, - product: product, - toolsVersion: package.manifest.toolsVersion, - buildParameters: destination == .host ? toolsBuildParameters : destinationBuildParameters, - fileSystem: fileSystem, - observabilityScope: planningObservabilityScope - )) + try productMap.insert( + ProductBuildDescription( + package: package, + product: product, + toolsVersion: package.manifest.toolsVersion, + buildParameters: destination == .host ? toolsBuildParameters : destinationBuildParameters, + fileSystem: fileSystem, + observabilityScope: planningObservabilityScope + ) + ) }, onModule: { module, destination in guard let package = graph.package(for: module) else { @@ -310,8 +312,9 @@ public class BuildPlan: SPMBuildCore.BuildPlan { product: product, forTarget: module, buildEnvironment: buildParameters.buildEnvironment, - observabilityScope: planningObservabilityScope - .makeChildScope(description: "Validate Deployment of Dependency") + observabilityScope: + planningObservabilityScope + .makeChildScope(description: "Validate Deployment of Dependency") ) } } @@ -350,39 +353,43 @@ public class BuildPlan: SPMBuildCore.BuildPlan { var generateTestObservation = false if module.type == .test && shouldGenerateTestObservation { generateTestObservation = true - shouldGenerateTestObservation = false // Only generate the code once. + shouldGenerateTestObservation = false // Only generate the code once. } - try targetMap.insert(.swift( - SwiftModuleBuildDescription( - package: package, - target: module, - toolsVersion: package.manifest.toolsVersion, - additionalFileRules: additionalFileRules, - buildParameters: buildParameters, - macroBuildParameters: toolsBuildParameters, - buildToolPluginInvocationResults: buildToolPluginInvocationResults[module.id] ?? [], - prebuildCommandResults: prebuildCommandResults[module.id] ?? [], - shouldGenerateTestObservation: generateTestObservation, - shouldDisableSandbox: disableSandbox, - fileSystem: fileSystem, - observabilityScope: planningObservabilityScope + try targetMap.insert( + .swift( + SwiftModuleBuildDescription( + package: package, + target: module, + toolsVersion: package.manifest.toolsVersion, + additionalFileRules: additionalFileRules, + buildParameters: buildParameters, + macroBuildParameters: toolsBuildParameters, + buildToolPluginInvocationResults: buildToolPluginInvocationResults[module.id] ?? [], + prebuildCommandResults: prebuildCommandResults[module.id] ?? [], + shouldGenerateTestObservation: generateTestObservation, + shouldDisableSandbox: disableSandbox, + fileSystem: fileSystem, + observabilityScope: planningObservabilityScope + ) ) - )) + ) case is ClangModule: - try targetMap.insert(.clang( - ClangModuleBuildDescription( - package: package, - target: module, - toolsVersion: package.manifest.toolsVersion, - additionalFileRules: additionalFileRules, - buildParameters: buildParameters, - buildToolPluginInvocationResults: buildToolPluginInvocationResults[module.id] ?? [], - prebuildCommandResults: prebuildCommandResults[module.id] ?? [], - fileSystem: fileSystem, - observabilityScope: planningObservabilityScope + try targetMap.insert( + .clang( + ClangModuleBuildDescription( + package: package, + target: module, + toolsVersion: package.manifest.toolsVersion, + additionalFileRules: additionalFileRules, + buildParameters: buildParameters, + buildToolPluginInvocationResults: buildToolPluginInvocationResults[module.id] ?? [], + prebuildCommandResults: prebuildCommandResults[module.id] ?? [], + fileSystem: fileSystem, + observabilityScope: planningObservabilityScope + ) ) - )) + ) case is PluginModule: try module.dependencies.compactMap { switch $0 { @@ -395,23 +402,27 @@ public class BuildPlan: SPMBuildCore.BuildPlan { return nil } }.forEach { - try productMap.insert(ProductBuildDescription( - package: package, - product: $0, - toolsVersion: package.manifest.toolsVersion, - buildParameters: toolsBuildParameters, - fileSystem: fileSystem, - observabilityScope: planningObservabilityScope - )) + try productMap.insert( + ProductBuildDescription( + package: package, + product: $0, + toolsVersion: package.manifest.toolsVersion, + buildParameters: toolsBuildParameters, + fileSystem: fileSystem, + observabilityScope: planningObservabilityScope + ) + ) } - try pluginDescriptions.append(PluginBuildDescription( - module: module, - products: package.products.filter { $0.modules.contains(id: module.id) }, - package: package, - toolsVersion: package.manifest.toolsVersion, - fileSystem: fileSystem - )) + try pluginDescriptions.append( + PluginBuildDescription( + module: module, + products: package.products.filter { $0.modules.contains(id: module.id) }, + package: package, + toolsVersion: package.manifest.toolsVersion, + fileSystem: fileSystem + ) + ) case is SystemLibraryModule, is BinaryModule: break default: @@ -446,9 +457,11 @@ public class BuildPlan: SPMBuildCore.BuildPlan { for item in derivedTestTargets { var derivedTestTargets = [item.entryPointTargetBuildDescription.target] - targetMap.insert(.swift( - item.entryPointTargetBuildDescription - )) + targetMap.insert( + .swift( + item.entryPointTargetBuildDescription + ) + ) if let discoveryTargetBuildDescription = item.discoveryTargetBuildDescription { targetMap.insert(.swift(discoveryTargetBuildDescription)) @@ -490,12 +503,14 @@ public class BuildPlan: SPMBuildCore.BuildPlan { // // If the product's platform version is greater than ours, then it is incompatible. if productPlatform.version > targetPlatform.version { - observabilityScope.emit(.productRequiresHigherPlatformVersion( - target: target, - targetPlatform: targetPlatform, - product: product.name, - productPlatform: productPlatform - )) + observabilityScope.emit( + .productRequiresHigherPlatformVersion( + target: target, + targetPlatform: targetPlatform, + product: product.name, + productPlatform: productPlatform + ) + ) } } @@ -694,12 +709,13 @@ public class BuildPlan: SPMBuildCore.BuildPlan { for product: ResolvedProduct, context: BuildParameters.Destination ) -> ProductBuildDescription? { - let destination: BuildParameters.Destination = switch product.type { - case .macro, .plugin: - .host - default: - context - } + let destination: BuildParameters.Destination = + switch product.type { + case .macro, .plugin: + .host + default: + context + } return self.productMap[.init(productID: product.id, destination: destination)] } @@ -708,12 +724,13 @@ public class BuildPlan: SPMBuildCore.BuildPlan { for module: ResolvedModule, context: BuildParameters.Destination ) -> ModuleBuildDescription? { - let destination: BuildParameters.Destination = switch module.type { - case .macro, .plugin: - .host - default: - context - } + let destination: BuildParameters.Destination = + switch module.type { + case .macro, .plugin: + .host + default: + context + } return self.targetMap[.init(moduleID: module.id, destination: destination)] } @@ -832,7 +849,6 @@ extension BuildPlan { observabilityScope: observabilityScope ) - if surfaceDiagnostics { let diagnosticsEmitter = observabilityScope.makeDiagnosticsEmitter { var metadata = ObservabilityMetadata() @@ -874,8 +890,7 @@ extension BuildPlan { for command in pluginResult.prebuildCommands { observabilityScope .emit( - info: "Running " + - (command.configuration.displayName ?? command.configuration.executable.basename) + info: "Running " + (command.configuration.displayName ?? command.configuration.executable.basename) ) // Run the command configuration as a subshell. This doesn't return until it is done. @@ -978,7 +993,7 @@ extension BuildPlan { var successors: [TraversalNode] = [] for product in package.products { if case .test = product.underlying.type, - !graph.rootPackages.contains(id: package.id) + !graph.rootPackages.contains(id: package.id) { continue } @@ -1073,7 +1088,7 @@ extension BuildPlan { var successors: [TraversalNode] = [] for product in package.products { if case .test = product.underlying.type, - !graph.rootPackages.contains(id: package.id) + !graph.rootPackages.contains(id: package.id) { continue } @@ -1136,12 +1151,13 @@ extension BuildPlan { successors(for: product, destination: destination) } } onNext: { current, parent in - let parentModule: (ResolvedModule, BuildParameters.Destination)? = switch parent { - case .package, .product, nil: - nil - case .module(let module, let destination): - (module, destination) - } + let parentModule: (ResolvedModule, BuildParameters.Destination)? = + switch parent { + case .package, .product, nil: + nil + case .module(let module, let destination): + (module, destination) + } switch current { case .package, .product: @@ -1242,7 +1258,7 @@ extension BuildPlan { guard product.type != .plugin else { return } - + guard product.type != .macro || parentModule.type == .test else { return } @@ -1252,7 +1268,7 @@ extension BuildPlan { guard childModule.type != .plugin else { return } - + guard childModule.type != .macro || parentModule.type == .test else { return } @@ -1306,16 +1322,18 @@ extension Basics.Diagnostic { product: String, productPlatform: SupportedPlatform ) -> Self { - .error(""" - the \(target.type.rawValue) '\(target.name)' requires \ - \(targetPlatform.platform.name) \(targetPlatform.version.versionString), \ - but depends on the product '\(product)' which requires \ - \(productPlatform.platform.name) \(productPlatform.version.versionString); \ - consider changing the \(target.type.rawValue) '\(target.name)' to require \ - \(productPlatform.platform.name) \(productPlatform.version.versionString) or later, \ - or the product '\(product)' to require \ - \(targetPlatform.platform.name) \(targetPlatform.version.versionString) or earlier. - """) + .error( + """ + the \(target.type.rawValue) '\(target.name)' requires \ + \(targetPlatform.platform.name) \(targetPlatform.version.versionString), \ + but depends on the product '\(product)' which requires \ + \(productPlatform.platform.name) \(productPlatform.version.versionString); \ + consider changing the \(target.type.rawValue) '\(target.name)' to require \ + \(productPlatform.platform.name) \(productPlatform.version.versionString) or later, \ + or the product '\(product)' to require \ + \(targetPlatform.platform.name) \(targetPlatform.version.versionString) or earlier. + """ + ) } static func binaryTargetsNotSupported() -> Self { @@ -1343,15 +1361,15 @@ func generateResourceInfoPlist( try fileSystem.writeIfChanged( path: path, string: """ - - - - - CFBundleDevelopmentRegion - \(defaultLocalization) - - - """ + + + + + CFBundleDevelopmentRegion + \(defaultLocalization) + + + """ ) return true } diff --git a/Sources/Build/LLBuildCommands.swift b/Sources/Build/LLBuildCommands.swift index aeb9442eb19..ddc29df564a 100644 --- a/Sources/Build/LLBuildCommands.swift +++ b/Sources/Build/LLBuildCommands.swift @@ -18,11 +18,11 @@ import SPMLLBuild import PackageModel #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import SwiftDriver -@_implementationOnly import SwiftOptions + @_implementationOnly import SwiftDriver + @_implementationOnly import SwiftOptions #else -import SwiftDriver -import SwiftOptions + import SwiftDriver + import SwiftOptions #endif import class TSCBasic.LocalFileOutputByteStream @@ -126,15 +126,18 @@ final class TestDiscoveryCommand: CustomLLBuildCommand, TestBuildCommand { let store = try IndexStore.open(store: TSCAbsolutePath(index), api: api) // FIXME: We can speed this up by having one llbuild command per object file. - let tests = try store + let tests = + try store .listTests(in: tool.inputs.map { try TSCAbsolutePath(AbsolutePath(validating: $0.name)) }) let testsByModule = Dictionary(grouping: tests, by: { $0.module.spm_mangledToC99ExtendedIdentifier() }) // Find the main file path. - guard let mainFile = outputs.first(where: { path in - path.basename == TestDiscoveryTool.mainFileName - }) else { + guard + let mainFile = outputs.first(where: { path in + path.basename == TestDiscoveryTool.mainFileName + }) + else { throw InternalError("main output (\(TestDiscoveryTool.mainFileName)) not found") } @@ -210,9 +213,11 @@ final class TestEntryPointCommand: CustomLLBuildCommand, TestBuildCommand { // Find the main output file let mainFileName = TestEntryPointTool.mainFileName - guard let mainFile = outputs.first(where: { path in - path.basename == mainFileName - }) else { + guard + let mainFile = outputs.first(where: { path in + path.basename == mainFileName + }) + else { throw InternalError("main file output (\(mainFileName)) not found") } @@ -231,19 +236,21 @@ final class TestEntryPointCommand: CustomLLBuildCommand, TestBuildCommand { testObservabilitySetup = "" } - let isXCTMainAvailable: String = switch buildParameters.testProductStyle { - case .entryPointExecutable: - "canImport(XCTest)" - case .loadableBundle: - "false" - } + let isXCTMainAvailable: String = + switch buildParameters.testProductStyle { + case .entryPointExecutable: + "canImport(XCTest)" + case .loadableBundle: + "false" + } /// On WASI, we can't block the main thread, so XCTestMain is defined as async. - let awaitXCTMainKeyword = if buildParameters.triple.isWASI() { - "await" - } else { - "" - } + let awaitXCTMainKeyword = + if buildParameters.triple.isWASI() { + "await" + } else { + "" + } var needsAsyncMainWorkaround = false if buildParameters.triple.isLinux() { @@ -396,7 +403,7 @@ final class WriteAuxiliaryFileCommand: CustomLLBuildCommand { func getFileContents(tool: WriteAuxiliaryFile) throws -> String { guard tool.inputs.first?.kind == .virtual, - let generatedFileType = tool.inputs.first?.name.dropFirst().dropLast() + let generatedFileType = tool.inputs.first?.name.dropFirst().dropLast() else { throw StringError("invalid inputs") } diff --git a/Sources/Build/LLBuildDescription.swift b/Sources/Build/LLBuildDescription.swift index 6dfa5fca2fa..1d27e16b1fb 100644 --- a/Sources/Build/LLBuildDescription.swift +++ b/Sources/Build/LLBuildDescription.swift @@ -107,7 +107,8 @@ public struct BuildDescription: Codable { self.testEntryPointCommands = testEntryPointCommands self.copyCommands = copyCommands self.writeCommands = writeCommands - self.explicitTargetDependencyImportCheckingMode = plan.destinationBuildParameters.driverParameters + self.explicitTargetDependencyImportCheckingMode = + plan.destinationBuildParameters.driverParameters .explicitTargetDependencyImportCheckingMode self.traitConfiguration = traitConfiguration self.targetDependencyMap = try plan.targets diff --git a/Sources/Build/LLBuildProgressTracker.swift b/Sources/Build/LLBuildProgressTracker.swift index 63a6a6caace..c12f3d6835e 100644 --- a/Sources/Build/LLBuildProgressTracker.swift +++ b/Sources/Build/LLBuildProgressTracker.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import Dispatch import Foundation import LLBuildManifest @@ -26,9 +25,9 @@ import class TSCBasic.ThreadSafeOutputByteStream import class TSCUtility.IndexStoreAPI #if canImport(llbuildSwift) -typealias LLBuildBuildSystemDelegate = llbuildSwift.BuildSystemDelegate + typealias LLBuildBuildSystemDelegate = llbuildSwift.BuildSystemDelegate #else -typealias LLBuildBuildSystemDelegate = llbuild.BuildSystemDelegate + typealias LLBuildBuildSystemDelegate = llbuild.BuildSystemDelegate #endif private final class InProcessTool: Tool { @@ -103,24 +102,24 @@ public final class BuildExecutionContext { self.indexStoreAPICache.memoize { do { #if os(Windows) - // The library's runtime component is in the `bin` directory on - // Windows rather than the `lib` directory as on Unix. The `lib` - // directory contains the import library (and possibly static - // archives) which are used for linking. The runtime component is - // not (necessarily) part of the SDK distributions. - // - // NOTE: the library name here `libIndexStore.dll` is technically - // incorrect as per the Windows naming convention. However, the - // library is currently installed as `libIndexStore.dll` rather than - // `IndexStore.dll`. In the future, this may require a fallback - // search, preferring `IndexStore.dll` over `libIndexStore.dll`. - let indexStoreLib = self.toolsBuildParameters.toolchain.swiftCompilerPath - .parentDirectory - .appending("libIndexStore.dll") + // The library's runtime component is in the `bin` directory on + // Windows rather than the `lib` directory as on Unix. The `lib` + // directory contains the import library (and possibly static + // archives) which are used for linking. The runtime component is + // not (necessarily) part of the SDK distributions. + // + // NOTE: the library name here `libIndexStore.dll` is technically + // incorrect as per the Windows naming convention. However, the + // library is currently installed as `libIndexStore.dll` rather than + // `IndexStore.dll`. In the future, this may require a fallback + // search, preferring `IndexStore.dll` over `libIndexStore.dll`. + let indexStoreLib = self.toolsBuildParameters.toolchain.swiftCompilerPath + .parentDirectory + .appending("libIndexStore.dll") #else - let ext = self.toolsBuildParameters.triple.dynamicLibraryExtension - let indexStoreLib = try toolsBuildParameters.toolchain.toolchainLibDir - .appending("libIndexStore" + ext) + let ext = self.toolsBuildParameters.triple.dynamicLibraryExtension + let indexStoreLib = try toolsBuildParameters.toolchain.toolchainLibDir + .appending("libIndexStore" + ext) #endif return try .success(IndexStoreAPI(dylib: TSCAbsolutePath(indexStoreLib))) } catch { @@ -175,9 +174,10 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut self.observabilityScope = observabilityScope self.delegate = delegate - let swiftParsers = buildExecutionContext.buildDescription?.swiftCommands.mapValues { tool in - SwiftCompilerOutputParser(targetName: tool.moduleName, delegate: self) - } ?? [:] + let swiftParsers = + buildExecutionContext.buildDescription?.swiftCommands.mapValues { tool in + SwiftCompilerOutputParser(targetName: tool.moduleName, delegate: self) + } ?? [:] self.swiftParsers = swiftParsers self.taskTracker.onTaskProgressUpdateText = { [weak self] progressText, _ in @@ -242,7 +242,7 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut func commandStatusChanged(_ command: SPMLLBuild.Command, kind: CommandStatusKind) { guard !self.logLevel.isVerbose, - !self.logLevel.isQuiet + !self.logLevel.isQuiet else { return } guard command.shouldShowStatus else { return } guard !self.swiftParsers.keys.contains(command.name) else { return } @@ -346,8 +346,10 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut result: CommandExtendedResult ) { // FIXME: This should really happen at the command-level and is just a stopgap measure. - let shouldFilterOutput = !self.logLevel.isVerbose && command.verboseDescription.hasPrefix("codesign ") && result - .result != .failed + let shouldFilterOutput = + !self.logLevel.isVerbose && command.verboseDescription.hasPrefix("codesign ") + && result + .result != .failed let commandName = command.name @@ -461,9 +463,7 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut if output.utf8.count < 1024 * 10 { let regex = try! RegEx(pattern: #".*(error:[^\n]*)\n.*"#, options: .dotMatchesLineSeparators) for match in regex.matchGroups(in: output) { - self.errorMessagesByTarget[parser.targetName] = ( - self.errorMessagesByTarget[parser.targetName] ?? [] - ) + [match[0]] + self.errorMessagesByTarget[parser.targetName] = (self.errorMessagesByTarget[parser.targetName] ?? []) + [match[0]] } } } @@ -486,11 +486,12 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut } func buildComplete(success: Bool, duration: DispatchTimeInterval, subsetDescriptor: String? = nil) { - let subsetString = if let subsetDescriptor { - "of \(subsetDescriptor) " - } else { - "" - } + let subsetString = + if let subsetDescriptor { + "of \(subsetDescriptor) " + } else { + "" + } self.queue.sync { self.progressAnimation.complete(success: success) @@ -571,14 +572,14 @@ private struct CommandTaskTracker { } private func progressText(of commandDescription: String, targetName: String?) -> String { -#if os(Windows) - let pathSep: Character = "\\" -#else - let pathSep: Character = "/" -#endif + #if os(Windows) + let pathSep: Character = "\\" + #else + let pathSep: Character = "/" + #endif // Transforms descriptions like "Linking ./.build/x86_64-apple-macosx/debug/foo" into "Linking foo". if let firstSpaceIndex = commandDescription.firstIndex(of: " "), - let lastDirectorySeparatorIndex = commandDescription.lastIndex(of: pathSep) + let lastDirectorySeparatorIndex = commandDescription.lastIndex(of: pathSep) { let action = commandDescription[.. = [] @@ -180,7 +190,8 @@ struct APIDiff: AsyncSwiftCommand { return results } - let failedModules = modulesToDiff + let failedModules = + modulesToDiff .subtracting(skippedModules) .subtracting(results.map(\.moduleName)) for failedModule in failedModules { @@ -331,10 +342,12 @@ struct APIDiff: AsyncSwiftCommand { modulesToDiff.formUnion(packageGraph.apiDigesterModules) } else { for productName in productNames { - guard let product = packageGraph + guard + let product = packageGraph .rootPackages .flatMap(\.products) - .first(where: { $0.name == productName }) else { + .first(where: { $0.name == productName }) + else { if diagnoseMissingNames { observabilityScope.emit(error: "no such product '\(productName)'") } @@ -349,10 +362,12 @@ struct APIDiff: AsyncSwiftCommand { modulesToDiff.formUnion(product.modules.filter { $0.underlying is SwiftModule }.map(\.c99name)) } for targetName in targetNames { - guard let target = packageGraph + guard + let target = packageGraph .rootPackages .flatMap(\.modules) - .first(where: { $0.name == targetName }) else { + .first(where: { $0.name == targetName }) + else { if diagnoseMissingNames { observabilityScope.emit(error: "no such target '\(targetName)'") } diff --git a/Sources/Commands/PackageCommands/AddDependency.swift b/Sources/Commands/PackageCommands/AddDependency.swift index 8a5381fd130..520c860bde4 100644 --- a/Sources/Commands/PackageCommands/AddDependency.swift +++ b/Sources/Commands/PackageCommands/AddDependency.swift @@ -140,11 +140,12 @@ extension SwiftPackageCommand { let requirement: PackageDependency.SourceControl.Requirement switch firstRequirement { case .range(let lowerBound, _), .rangeFrom(let lowerBound): - requirement = if let to { - .range(lowerBound: lowerBound, upperBound: to.description) - } else { - firstRequirement - } + requirement = + if let to { + .range(lowerBound: lowerBound, upperBound: to.description) + } else { + firstRequirement + } default: requirement = firstRequirement @@ -200,11 +201,12 @@ extension SwiftPackageCommand { let requirement: PackageDependency.Registry.Requirement switch firstRequirement { case .range(let lowerBound, _), .rangeFrom(let lowerBound): - requirement = if let to { - .range(lowerBound: lowerBound, upperBound: to.description) - } else { - firstRequirement - } + requirement = + if let to { + .range(lowerBound: lowerBound, upperBound: to.description) + } else { + firstRequirement + } default: requirement = firstRequirement diff --git a/Sources/Commands/PackageCommands/AddProduct.swift b/Sources/Commands/PackageCommands/AddProduct.swift index 2a0ab921b28..5142d2dae0c 100644 --- a/Sources/Commands/PackageCommands/AddProduct.swift +++ b/Sources/Commands/PackageCommands/AddProduct.swift @@ -81,13 +81,14 @@ extension SwiftPackageCommand { } // Map the product type. - let type: ProductDescription.ProductType = switch self.type { - case .executable: .executable - case .library: .library(.automatic) - case .dynamicLibrary: .library(.dynamic) - case .staticLibrary: .library(.static) - case .plugin: .plugin - } + let type: ProductDescription.ProductType = + switch self.type { + case .executable: .executable + case .library: .library(.automatic) + case .dynamicLibrary: .library(.dynamic) + case .staticLibrary: .library(.static) + case .plugin: .plugin + } let product = ProductDescription( name: name, @@ -109,4 +110,3 @@ extension SwiftPackageCommand { } } } - diff --git a/Sources/Commands/PackageCommands/AddTarget.swift b/Sources/Commands/PackageCommands/AddTarget.swift index 58cfb4dd996..90180ad1b1e 100644 --- a/Sources/Commands/PackageCommands/AddTarget.swift +++ b/Sources/Commands/PackageCommands/AddTarget.swift @@ -110,12 +110,13 @@ extension SwiftPackageCommand { ) // Map the target type. - let type: PackageTarget.TargetKind = switch self.type { - case .library: .library - case .executable: .executable - case .test: .test - case .macro: .macro - } + let type: PackageTarget.TargetKind = + switch self.type { + case .library: .library + case .executable: .executable + case .test: .test + case .macro: .macro + } // Map dependencies let dependencies: [PackageTarget.Dependency] = self.dependencies.map { @@ -258,11 +259,12 @@ extension SwiftPackageCommand { fileSystem: any FileSystem, rootPath: AbsolutePath ) throws { - let outerDirectory: String? = switch target.type { - case .binary, .plugin, .system: nil - case .executable, .library, .macro: "Sources" - case .test: "Tests" - } + let outerDirectory: String? = + switch target.type { + case .binary, .plugin, .system: nil + case .executable, .library, .macro: "Sources" + case .test: "Tests" + } guard let outerDirectory else { return @@ -275,8 +277,8 @@ extension SwiftPackageCommand { var importModuleNames = target.dependencies.map { switch $0 { case .byName(let name), - .target(let name), - .product(let name, package: _): + .target(let name), + .product(let name, package: _): name } } @@ -314,16 +316,16 @@ extension SwiftPackageCommand { files.addSourceFile( path: sourceFilePath, sourceCode: """ - \(imports) - struct \(raw: target.sanitizedName): Macro { - /// TODO: Implement one or more of the protocols that inherit - /// from Macro. The appropriate macro protocol is determined - /// by the "macro" declaration that \(raw: target.sanitizedName) implements. - /// Examples include: - /// @freestanding(expression) macro --> ExpressionMacro - /// @attached(member) macro --> MemberMacro - } - """ + \(imports) + struct \(raw: target.sanitizedName): Macro { + /// TODO: Implement one or more of the protocols that inherit + /// from Macro. The appropriate macro protocol is determined + /// by the "macro" declaration that \(raw: target.sanitizedName) implements. + /// Examples include: + /// @freestanding(expression) macro --> ExpressionMacro + /// @attached(member) macro --> MemberMacro + } + """ ) // Add a file that introduces the main entrypoint and provided macros @@ -331,47 +333,48 @@ extension SwiftPackageCommand { files.addSourceFile( path: targetDir.appending(component: "ProvidedMacros.swift"), sourceCode: """ - import SwiftCompilerPlugin + import SwiftCompilerPlugin - @main - struct \(raw: target.sanitizedName)Macros: CompilerPlugin { - let providingMacros: [Macro.Type] = [ - \(raw: target.sanitizedName).self, - ] - } - """ + @main + struct \(raw: target.sanitizedName)Macros: CompilerPlugin { + let providingMacros: [Macro.Type] = [ + \(raw: target.sanitizedName).self, + ] + } + """ ) case .test: - let sourceCode: SourceFileSyntax = switch testHarness { - case .none: - """ - \(imports) - // Test code here - """ + let sourceCode: SourceFileSyntax = + switch testHarness { + case .none: + """ + \(imports) + // Test code here + """ - case .xctest: - """ - \(imports) - class \(raw: target.sanitizedName)Tests: XCTestCase { - func test\(raw: target.sanitizedName)() { - XCTAssertEqual(42, 17 + 25) + case .xctest: + """ + \(imports) + class \(raw: target.sanitizedName)Tests: XCTestCase { + func test\(raw: target.sanitizedName)() { + XCTAssertEqual(42, 17 + 25) + } } - } - """ + """ - case .swiftTesting: - """ - \(imports) - @Suite - struct \(raw: target.sanitizedName)Tests { - @Test("\(raw: target.sanitizedName) tests") - func example() { - #expect(42 == 17 + 25) + case .swiftTesting: + """ + \(imports) + @Suite + struct \(raw: target.sanitizedName)Tests { + @Test("\(raw: target.sanitizedName) tests") + func example() { + #expect(42 == 17 + 25) + } } + """ } - """ - } files.addSourceFile(path: sourceFilePath, sourceCode: sourceCode) @@ -379,22 +382,22 @@ extension SwiftPackageCommand { files.addSourceFile( path: sourceFilePath, sourceCode: """ - \(imports) - """ + \(imports) + """ ) case .executable: files.addSourceFile( path: sourceFilePath, sourceCode: """ - \(imports) - @main - struct \(raw: target.sanitizedName)Main { - static func main() { - print("Hello, world") + \(imports) + @main + struct \(raw: target.sanitizedName)Main { + static func main() { + print("Hello, world") + } } - } - """ + """ ) } diff --git a/Sources/Commands/PackageCommands/AddTargetDependency.swift b/Sources/Commands/PackageCommands/AddTargetDependency.swift index 47cded60850..8947aab79d2 100644 --- a/Sources/Commands/PackageCommands/AddTargetDependency.swift +++ b/Sources/Commands/PackageCommands/AddTargetDependency.swift @@ -92,4 +92,3 @@ extension SwiftPackageCommand { } } } - diff --git a/Sources/Commands/PackageCommands/ArchiveSource.swift b/Sources/Commands/PackageCommands/ArchiveSource.swift index 82ee0d4e52f..a09a920e82e 100644 --- a/Sources/Commands/PackageCommands/ArchiveSource.swift +++ b/Sources/Commands/PackageCommands/ArchiveSource.swift @@ -42,7 +42,7 @@ extension SwiftPackageCommand { archivePath = output } else { let graph = try await swiftCommandState.loadPackageGraph() - let packageName = graph.rootPackages[graph.rootPackages.startIndex].manifest.displayName // TODO: use identity instead? + let packageName = graph.rootPackages[graph.rootPackages.startIndex].manifest.displayName // TODO: use identity instead? archivePath = packageDirectory.appending("\(packageName).zip") } diff --git a/Sources/Commands/PackageCommands/AuditBinaryArtifact.swift b/Sources/Commands/PackageCommands/AuditBinaryArtifact.swift index 80c50366488..752bd36c577 100644 --- a/Sources/Commands/PackageCommands/AuditBinaryArtifact.swift +++ b/Sources/Commands/PackageCommands/AuditBinaryArtifact.swift @@ -39,7 +39,8 @@ struct AuditBinaryArtifact: AsyncSwiftCommand { let clang = try hostToolchain.getClangCompiler() let objdump = try hostToolchain.getLLVMObjdump() let hostTriple = try Triple.getVersionedHostTriple( - usingSwiftCompiler: hostToolchain.swiftCompilerPath) + usingSwiftCompiler: hostToolchain.swiftCompilerPath + ) let fileSystem = swiftCommandState.fileSystem guard !(hostTriple.isDarwin() || hostTriple.isWindows()) else { @@ -51,17 +52,25 @@ struct AuditBinaryArtifact: AsyncSwiftCommand { var hostDefaultSymbols = ReferencedSymbols() let symbolProvider = LLVMObjdumpSymbolProvider(objdumpPath: objdump) for binary in try await detectDefaultObjects( - clang: clang, fileSystem: fileSystem, hostTriple: hostTriple, + clang: clang, + fileSystem: fileSystem, + hostTriple: hostTriple, observabilityScope: swiftCommandState.observabilityScope.makeChildScope( - description: "DefaultObjectsDetector")) - { + description: "DefaultObjectsDetector" + ) + ) { try await symbolProvider.symbols( - for: binary, symbols: &hostDefaultSymbols, recordUndefined: false) + for: binary, + symbols: &hostDefaultSymbols, + recordUndefined: false + ) } let extractedArtifact = try await extractArtifact( - fileSystem: fileSystem, scratchDirectory: swiftCommandState.scratchDirectory) + fileSystem: fileSystem, + scratchDirectory: swiftCommandState.scratchDirectory + ) guard let artifactKind = try Workspace.BinaryArtifactsManager.deriveBinaryArtifactKind( @@ -74,11 +83,15 @@ struct AuditBinaryArtifact: AsyncSwiftCommand { } let module = BinaryModule( - name: path.basenameWithoutExt, kind: artifactKind, path: extractedArtifact, - origin: .local) + name: path.basenameWithoutExt, + kind: artifactKind, + path: extractedArtifact, + origin: .local + ) for library in try module.parseLibraryArtifactArchives( - for: hostTriple, fileSystem: fileSystem) - { + for: hostTriple, + fileSystem: fileSystem + ) { var symbols = hostDefaultSymbols try await symbolProvider.symbols(for: library.libraryPath, symbols: &symbols) @@ -104,7 +117,8 @@ struct AuditBinaryArtifact: AsyncSwiftCommand { let archiver = UniversalArchiver(fileSystem) if let lastPathComponent = path.components.last, - lastPathComponent.hasSuffix("artifactbundle") { + lastPathComponent.hasSuffix("artifactbundle") + { return path } @@ -113,7 +127,8 @@ struct AuditBinaryArtifact: AsyncSwiftCommand { else { let supportedExtensionList = archiver.supportedExtensions.joined(separator: ", ") throw StringError( - "unexpected file type; supported extensions are: \(supportedExtensionList)") + "unexpected file type; supported extensions are: \(supportedExtensionList)" + ) } // Ensure that the path with the accepted extension is a file. @@ -123,7 +138,8 @@ struct AuditBinaryArtifact: AsyncSwiftCommand { let archiveDirectory = scratchDirectory.appending( components: "artifact-auditing", - path.basenameWithoutExt, UUID().uuidString + path.basenameWithoutExt, + UUID().uuidString ) try fileSystem.forceCreateDirectory(at: archiveDirectory) diff --git a/Sources/Commands/PackageCommands/Config.swift b/Sources/Commands/PackageCommands/Config.swift index ef2720f2682..dd14ab84968 100644 --- a/Sources/Commands/PackageCommands/Config.swift +++ b/Sources/Commands/PackageCommands/Config.swift @@ -129,8 +129,9 @@ extension SwiftPackageCommand.Config { ) } - guard let originalOrMirror = self._deprecate_packageURL ?? self._deprecate_originalURL ?? self - .original ?? self._deprecate_mirrorURL ?? self.mirror + guard + let originalOrMirror = self._deprecate_packageURL ?? self._deprecate_originalURL ?? self + .original ?? self._deprecate_mirrorURL ?? self.mirror else { swiftCommandState.observabilityScope.emit(.missingRequiredArg("--original or --mirror")) throw ExitCode.failure diff --git a/Sources/Commands/PackageCommands/Describe.swift b/Sources/Commands/PackageCommands/Describe.swift index cdf9c1b7165..067302fa3b0 100644 --- a/Sources/Commands/PackageCommands/Describe.swift +++ b/Sources/Commands/PackageCommands/Describe.swift @@ -29,17 +29,17 @@ extension SwiftPackageCommand { @OptionGroup(visibility: .hidden) var globalOptions: GlobalOptions - + @Option(help: "Set the output format.") var type: DescribeMode = .text - + func run(_ swiftCommandState: SwiftCommandState) async throws { let workspace = try swiftCommandState.getActiveWorkspace() - + guard let packagePath = try swiftCommandState.getWorkspaceRoot().packages.first else { throw StringError("unknown package") } - + let package = try await workspace.loadRootPackage( at: packagePath, observabilityScope: swiftCommandState.observabilityScope @@ -47,7 +47,7 @@ extension SwiftPackageCommand { try self.describe(package, in: type) } - + /// Emits a textual description of `package` to `stream`, in the format indicated by `mode`. func describe(_ package: Package, in mode: DescribeMode) throws { let desc = DescribedPackage(from: package) @@ -66,7 +66,7 @@ extension SwiftPackageCommand { } print(String(decoding: data, as: UTF8.self)) } - + enum DescribeMode: String, ExpressibleByArgument, CaseIterable { /// JSON format (guaranteed to be parsable and stable across time). case json diff --git a/Sources/Commands/PackageCommands/DumpCommands.swift b/Sources/Commands/PackageCommands/DumpCommands.swift index f0b5aa81da1..b2c055ef27e 100644 --- a/Sources/Commands/PackageCommands/DumpCommands.swift +++ b/Sources/Commands/PackageCommands/DumpCommands.swift @@ -45,7 +45,7 @@ struct DumpSymbolGraph: AsyncSwiftCommand { @Flag(help: "Add symbols with SPI information to the symbol graph.") var includeSPISymbols = false - + @Flag(help: "Emit extension block symbols for extensions to external types or directly associate members and conformances with the extended nominal.") var extensionBlockSymbolBehavior: ExtensionBlockSymbolBehavior = .omitExtensionBlockSymbols @@ -58,16 +58,21 @@ struct DumpSymbolGraph: AsyncSwiftCommand { enableAllTraits: true, cacheBuildManifest: false ) - let buildResult = try await buildSystem.build(subset: .allExcludingTests, buildOutputs: [.symbolGraph( - BuildOutput.SymbolGraphOptions( - prettyPrint: prettyPrint, - minimumAccessLevel: .accessLevel(minimumAccessLevel), - includeInheritedDocs: !skipInheritedDocs, - includeSynthesized: !skipSynthesizedMembers, - includeSPI: includeSPISymbols, - emitExtensionBlocks: extensionBlockSymbolBehavior != .omitExtensionBlockSymbols, - ) - ), .buildPlan]) + let buildResult = try await buildSystem.build( + subset: .allExcludingTests, + buildOutputs: [ + .symbolGraph( + BuildOutput.SymbolGraphOptions( + prettyPrint: prettyPrint, + minimumAccessLevel: .accessLevel(minimumAccessLevel), + includeInheritedDocs: !skipInheritedDocs, + includeSynthesized: !skipSynthesizedMembers, + includeSPI: includeSPISymbols, + emitExtensionBlocks: extensionBlockSymbolBehavior != .omitExtensionBlockSymbols, + ) + ), .buildPlan, + ] + ) let symbolGraphDirectory = try swiftCommandState.productsBuildParameters.dataPath.appending("symbolgraph") diff --git a/Sources/Commands/PackageCommands/EditCommands.swift b/Sources/Commands/PackageCommands/EditCommands.swift index 332e7f6b572..1a7ab159341 100644 --- a/Sources/Commands/PackageCommands/EditCommands.swift +++ b/Sources/Commands/PackageCommands/EditCommands.swift @@ -62,8 +62,10 @@ extension SwiftPackageCommand { @OptionGroup(visibility: .hidden) var globalOptions: GlobalOptions - @Flag(name: .customLong("force"), - help: "Unedit the package even if it has uncommitted and unpushed changes.") + @Flag( + name: .customLong("force"), + help: "Unedit the package even if it has uncommitted and unpushed changes." + ) var shouldForceRemove: Bool = false @Argument(help: "The identity of the package to unedit.") diff --git a/Sources/Commands/PackageCommands/Format.swift b/Sources/Commands/PackageCommands/Format.swift index e005ccd1c4e..cd9a5eb738e 100644 --- a/Sources/Commands/PackageCommands/Format.swift +++ b/Sources/Commands/PackageCommands/Format.swift @@ -25,15 +25,18 @@ import enum TSCUtility.Diagnostics extension SwiftPackageCommand { struct Format: AsyncSwiftCommand { static let configuration = CommandConfiguration( - commandName: "_format", shouldDisplay: false, + commandName: "_format", + shouldDisplay: false, helpNames: [.short, .long, .customLong("help", withSingleDash: true)] ) @OptionGroup(visibility: .private) var globalOptions: GlobalOptions - @Argument(parsing: .captureForPassthrough, - help: "Pass flag through to the swift-format tool.") + @Argument( + parsing: .captureForPassthrough, + help: "Pass flag through to the swift-format tool." + ) var swiftFormatFlags: [String] = [] func run(_ swiftCommandState: SwiftCommandState) async throws { @@ -57,9 +60,9 @@ extension SwiftPackageCommand { observabilityScope: swiftCommandState.observabilityScope ) - // Use the user provided flags or default to formatting mode. - let formatOptions = swiftFormatFlags.isEmpty + let formatOptions = + swiftFormatFlags.isEmpty ? ["--mode", "format", "--in-place", "--parallel"] : swiftFormatFlags @@ -71,7 +74,7 @@ extension SwiftPackageCommand { }.map { $0.pathString } let args = [swiftFormat.pathString] + formatOptions + [packagePath.pathString] + paths - print("Running:", args.map{ $0.spm_shellEscaped() }.joined(separator: " ")) + print("Running:", args.map { $0.spm_shellEscaped() }.joined(separator: " ")) let result = try await AsyncProcess.popen(arguments: args) let output = try (result.utf8Output() + result.utf8stderrOutput()) diff --git a/Sources/Commands/PackageCommands/Init.swift b/Sources/Commands/PackageCommands/Init.swift index 5758fff800b..b2cd6b006ed 100644 --- a/Sources/Commands/PackageCommands/Init.swift +++ b/Sources/Commands/PackageCommands/Init.swift @@ -13,8 +13,7 @@ import ArgumentParser import Basics -@_spi(SwiftPMInternal) -import CoreCommands +@_spi(SwiftPMInternal) import CoreCommands import PackageModel import Workspace @@ -29,20 +28,24 @@ extension SwiftPackageCommand { @OptionGroup(visibility: .hidden) var globalOptions: GlobalOptions - + @Option( name: .customLong("type"), - help: ArgumentHelp("Package type:", discussion: """ - library - A package with a library. - executable - A package with an executable. - tool - A package with an executable that uses - Swift Argument Parser. Use this template if you - plan to have a rich set of command-line arguments. - build-tool-plugin - A package that vends a build tool plugin. - command-plugin - A package that vends a command plugin. - macro - A package that vends a macro. - empty - An empty package with a Package.swift manifest. - """)) + help: ArgumentHelp( + "Package type:", + discussion: """ + library - A package with a library. + executable - A package with an executable. + tool - A package with an executable that uses + Swift Argument Parser. Use this template if you + plan to have a rich set of command-line arguments. + build-tool-plugin - A package that vends a build tool plugin. + command-plugin - A package that vends a command plugin. + macro - A package that vends a macro. + empty - An empty package with a Package.swift manifest. + """ + ) + ) var initMode: InitPackage.PackageType = .library /// Which testing libraries to use (and any related options.) @@ -66,12 +69,10 @@ extension SwiftPackageCommand { // For macros this is reversed, since we don't support testing // macros with Swift Testing yet. var supportedTestingLibraries = Set() - if testLibraryOptions.isExplicitlyEnabled(.xctest, swiftCommandState: swiftCommandState) || - (initMode == .macro && testLibraryOptions.isEnabled(.xctest, swiftCommandState: swiftCommandState)) { + if testLibraryOptions.isExplicitlyEnabled(.xctest, swiftCommandState: swiftCommandState) || (initMode == .macro && testLibraryOptions.isEnabled(.xctest, swiftCommandState: swiftCommandState)) { supportedTestingLibraries.insert(.xctest) } - if testLibraryOptions.isExplicitlyEnabled(.swiftTesting, swiftCommandState: swiftCommandState) || - (initMode != .macro && testLibraryOptions.isEnabled(.swiftTesting, swiftCommandState: swiftCommandState)) { + if testLibraryOptions.isExplicitlyEnabled(.swiftTesting, swiftCommandState: swiftCommandState) || (initMode != .macro && testLibraryOptions.isEnabled(.swiftTesting, swiftCommandState: swiftCommandState)) { supportedTestingLibraries.insert(.swiftTesting) } diff --git a/Sources/Commands/PackageCommands/Install.swift b/Sources/Commands/PackageCommands/Install.swift index 5a6b833a260..9171e53acd8 100644 --- a/Sources/Commands/PackageCommands/Install.swift +++ b/Sources/Commands/PackageCommands/Install.swift @@ -42,9 +42,9 @@ extension SwiftPackageCommand { if let path = env[.path], !path.contains(swiftpmBinDir.pathString), !globalOptions.logging.quiet { commandState.observabilityScope.emit( warning: """ - PATH doesn't include \(swiftpmBinDir.pathString)! This means you won't be able to access \ - the installed executables by default, and will need to specify the full path. - """ + PATH doesn't include \(swiftpmBinDir.pathString)! This means you won't be able to access \ + the installed executables by default, and will need to specify the full path. + """ ) } diff --git a/Sources/Commands/PackageCommands/Learn.swift b/Sources/Commands/PackageCommands/Learn.swift index ea10cdc7775..ecb67c81551 100644 --- a/Sources/Commands/PackageCommands/Learn.swift +++ b/Sources/Commands/PackageCommands/Learn.swift @@ -62,10 +62,12 @@ extension SwiftPackageCommand { let topLevelSnippets = try files(fileSystem: fileSystem, in: snippetsDirectory, fileExtension: "swift") .map { try Snippet(parsing: $0) } - let topLevelSnippetGroup = SnippetGroup(name: "Getting Started", - baseDirectory: snippetsDirectory, - snippets: topLevelSnippets, - explanation: "") + let topLevelSnippetGroup = SnippetGroup( + name: "Getting Started", + baseDirectory: snippetsDirectory, + snippets: topLevelSnippets, + explanation: "" + ) let subdirectoryGroups = try subdirectories(fileSystem: fileSystem, in: snippetsDirectory) .map { subdirectory -> SnippetGroup in @@ -81,15 +83,19 @@ extension SwiftPackageCommand { snippetGroupExplanation = "" } - return SnippetGroup(name: subdirectory.basename, - baseDirectory: subdirectory, - snippets: snippets, - explanation: snippetGroupExplanation) + return SnippetGroup( + name: subdirectory.basename, + baseDirectory: subdirectory, + snippets: snippets, + explanation: snippetGroupExplanation + ) } - let snippetGroups = [topLevelSnippetGroup] + subdirectoryGroups.sorted { - $0.baseDirectory.basename < $1.baseDirectory.basename - } + let snippetGroups = + [topLevelSnippetGroup] + + subdirectoryGroups.sorted { + $0.baseDirectory.basename < $1.baseDirectory.basename + } return snippetGroups.filter { !$0.snippets.isEmpty } } diff --git a/Sources/Commands/PackageCommands/Migrate.swift b/Sources/Commands/PackageCommands/Migrate.swift index d7485164f6e..fd9a640b05d 100644 --- a/Sources/Commands/PackageCommands/Migrate.swift +++ b/Sources/Commands/PackageCommands/Migrate.swift @@ -14,8 +14,7 @@ import ArgumentParser import Basics -@_spi(SwiftPMInternal) -import CoreCommands +@_spi(SwiftPMInternal) import CoreCommands import Foundation @@ -24,8 +23,7 @@ import OrderedCollections import PackageGraph import PackageModel -@_spi(PackageRefactor) -import enum SwiftRefactor.ManifestEditError +@_spi(PackageRefactor) import enum SwiftRefactor.ManifestEditError import SPMBuildCore import SwiftFixIt @@ -148,7 +146,7 @@ extension SwiftPackageCommand { .units( allowed: [.seconds], width: .narrow, - fractionalPart: .init(lengthLimits: 0 ... 3, roundingRule: .up) + fractionalPart: .init(lengthLimits: 0...3, roundingRule: .up) ) ) message += ")" @@ -191,7 +189,8 @@ extension SwiftPackageCommand { let feature = supportedFeatures.first { $0.name == name } guard let feature else { - let migratableCommaSeparatedFeatures = supportedFeatures + let migratableCommaSeparatedFeatures = + supportedFeatures .filter(\.migratable) .map(\.name) .sorted() @@ -285,23 +284,23 @@ extension SwiftPackageCommand { if let error = error as? ManifestEditError { switch error { case .cannotFindPackage, - .cannotAddSettingsToPluginTarget, - .existingDependency, - .malformedManifest: + .cannotAddSettingsToPluginTarget, + .existingDependency, + .malformedManifest: break case .cannotFindArrayLiteralArgument, - // This means the target could not be found - // syntactically, not that it does not exist. - .cannotFindTargets, - .cannotFindTarget: + // This means the target could not be found + // syntactically, not that it does not exist. + .cannotFindTargets, + .cannotFindTarget: let settings = try features.map { try $0.swiftSettingDescription }.joined(separator: ", ") message += """ - . Please enable them manually by adding the following Swift settings to the target: \ - '\(settings)' - """ + . Please enable them manually by adding the following Swift settings to the target: \ + '\(settings)' + """ } } diff --git a/Sources/Commands/PackageCommands/PluginCommand.swift b/Sources/Commands/PackageCommands/PluginCommand.swift index 31502178e6c..53d73e4942a 100644 --- a/Sources/Commands/PackageCommands/PluginCommand.swift +++ b/Sources/Commands/PackageCommands/PluginCommand.swift @@ -91,7 +91,7 @@ struct PluginCommand: AsyncSwiftCommand { } return parts[1] .split(separator: ",") - .compactMap{ String($0).spm_chuzzle() } + .compactMap { String($0).spm_chuzzle() } .compactMap { Int($0) } } @@ -203,13 +203,13 @@ struct PluginCommand: AsyncSwiftCommand { // merge the relevant plugin execution options let pluginOptions = options.merged(with: pluginArguments.pluginOptions) // sandbox is special since its generic not a specific plugin option - swiftCommandState.shouldDisableSandbox = swiftCommandState.shouldDisableSandbox || pluginArguments.globalOptions.security - .shouldDisableSandbox + swiftCommandState.shouldDisableSandbox = + swiftCommandState.shouldDisableSandbox + || pluginArguments.globalOptions.security + .shouldDisableSandbox let buildSystemKind = - pluginArguments.globalOptions.build.buildSystem != .native ? - pluginArguments.globalOptions.build.buildSystem : - swiftCommandState.options.build.buildSystem + pluginArguments.globalOptions.build.buildSystem != .native ? pluginArguments.globalOptions.build.buildSystem : swiftCommandState.options.build.buildSystem // At this point we know we found exactly one command plugin, so we run it. In SwiftPM CLI, we have only one root package. try await PluginCommand.run( @@ -267,24 +267,24 @@ struct PluginCommand: AsyncSwiftCommand { switch $0 { case .writeToPackageDirectory(let reason): - guard !options.allowWritingToPackageDirectory else { return } // permission already granted + guard !options.allowWritingToPackageDirectory else { return } // permission already granted permissionString = "write to the package directory" reasonString = reason remedyOption = "--allow-writing-to-package-directory" case .allowNetworkConnections(let scope, let reason): - guard scope != .none else { return } // no need to prompt - guard options.allowNetworkConnections != .init(scope) else { return } // permission already granted + guard scope != .none else { return } // no need to prompt + guard options.allowNetworkConnections != .init(scope) else { return } // permission already granted switch scope { case .all, .local: - let portsString = scope.ports - .isEmpty ? "on all ports" : - "on ports: \(scope.ports.map { "\($0)" }.joined(separator: ", "))" + let portsString = + scope.ports + .isEmpty ? "on all ports" : "on ports: \(scope.ports.map { "\($0)" }.joined(separator: ", "))" permissionString = "allow \(scope.label) network connections \(portsString)" case .docker, .unixDomainSocket: permissionString = "allow \(scope.label) connections" case .none: - permissionString = "" // should not be reached + permissionString = "" // should not be reached } reasonString = reason @@ -326,11 +326,13 @@ struct PluginCommand: AsyncSwiftCommand { } // Make sure that the package path is read-only unless it's covered by any of the explicitly writable directories. - let readOnlyDirectories = writableDirectories - .contains { package.path.isDescendantOfOrEqual(to: $0) } ? [] : [package.path] + let readOnlyDirectories = + writableDirectories + .contains { package.path.isDescendantOfOrEqual(to: $0) } ? [] : [package.path] // Use the directory containing the compiler as an additional search directory, and add the $PATH. - let toolSearchDirs = [try swiftCommandState.getTargetToolchain().swiftCompilerPath.parentDirectory] + let toolSearchDirs = + [try swiftCommandState.getTargetToolchain().swiftCompilerPath.parentDirectory] + getEnvSearchPaths(pathString: Environment.current[.path], currentWorkingDirectory: .none) var buildParameters = try swiftCommandState.toolsBuildParameters diff --git a/Sources/Commands/PackageCommands/ShowDependencies.swift b/Sources/Commands/PackageCommands/ShowDependencies.swift index 2998dc950f7..219709d7a72 100644 --- a/Sources/Commands/PackageCommands/ShowDependencies.swift +++ b/Sources/Commands/PackageCommands/ShowDependencies.swift @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// - import ArgumentParser import Basics import CoreCommands @@ -33,8 +32,10 @@ extension SwiftPackageCommand { @Option(help: "Set the output format.") var format: ShowDependenciesMode = .text - @Option(name: [.long, .customShort("o") ], - help: "The absolute or relative path to output the resolved dependency graph.") + @Option( + name: [.long, .customShort("o")], + help: "The absolute or relative path to output the resolved dependency graph." + ) var outputPath: AbsolutePath? func run(_ swiftCommandState: SwiftCommandState) async throws { diff --git a/Sources/Commands/PackageCommands/ShowExecutables.swift b/Sources/Commands/PackageCommands/ShowExecutables.swift index 09c74f30c79..db086848e1f 100644 --- a/Sources/Commands/PackageCommands/ShowExecutables.swift +++ b/Sources/Commands/PackageCommands/ShowExecutables.swift @@ -42,7 +42,7 @@ struct ShowExecutables: AsyncSwiftCommand { } else { return Executable(package: Optional.none, name: product.name) } - }.sorted(by: {$0.name < $1.name}) + }.sorted(by: { $0.name < $1.name }) switch self.format { case .flatlist: diff --git a/Sources/Commands/PackageCommands/ShowTraits.swift b/Sources/Commands/PackageCommands/ShowTraits.swift index edd8aaf3d99..2d0665c1753 100644 --- a/Sources/Commands/PackageCommands/ShowTraits.swift +++ b/Sources/Commands/PackageCommands/ShowTraits.swift @@ -36,15 +36,16 @@ struct ShowTraits: AsyncSwiftCommand { func run(_ swiftCommandState: SwiftCommandState) async throws { let packageGraph = try await swiftCommandState.loadPackageGraph() - let traits = if let packageId { - packageGraph.packages.filter({ $0.identity.description == packageId }).flatMap( { $0.manifest.traits } ).sorted(by: {$0.name < $1.name} ) - } else { - packageGraph.rootPackages.flatMap( { $0.manifest.traits } ).sorted(by: {$0.name < $1.name} ) - } + let traits = + if let packageId { + packageGraph.packages.filter({ $0.identity.description == packageId }).flatMap({ $0.manifest.traits }).sorted(by: { $0.name < $1.name }) + } else { + packageGraph.rootPackages.flatMap({ $0.manifest.traits }).sorted(by: { $0.name < $1.name }) + } switch self.format { case .text: - let defaultTraits = traits.filter( { $0.isDefault } ).flatMap( { $0.enabledTraits }) + let defaultTraits = traits.filter({ $0.isDefault }).flatMap({ $0.enabledTraits }) for trait in traits { guard !trait.isDefault else { diff --git a/Sources/Commands/PackageCommands/SwiftPackageCommand.swift b/Sources/Commands/PackageCommands/SwiftPackageCommand.swift index 6c7437fe991..10ae5f2d5ce 100644 --- a/Sources/Commands/PackageCommands/SwiftPackageCommand.swift +++ b/Sources/Commands/PackageCommands/SwiftPackageCommand.swift @@ -118,12 +118,13 @@ extension SwiftPackageCommand { if !pluginCommands.isEmpty { print("\nAVAILABLE PLUGIN COMMANDS:") for cmd in pluginCommands { - let formattedDescription = "\(cmd.name)" + let formattedDescription = + "\(cmd.name)" .padding(toLength: 24, withPad: " ", startingAt: 0) + cmd.description print(" " + formattedDescription) } } - } catch {} // fail silently as user does not need to know we could not fetch plugin command's for the + } catch {} // fail silently as user does not need to know we could not fetch plugin command's for the // help screen return } @@ -187,8 +188,10 @@ extension PluginCommand.PluginOptions { ) // actual merge var merged = self - merged.allowWritingToPackageDirectory = merged.allowWritingToPackageDirectory || other - .allowWritingToPackageDirectory + merged.allowWritingToPackageDirectory = + merged.allowWritingToPackageDirectory + || other + .allowWritingToPackageDirectory merged.additionalAllowedWritableDirectories.append(contentsOf: other.additionalAllowedWritableDirectories) if other.allowNetworkConnections != .none { merged.allowNetworkConnections = other.allowNetworkConnections diff --git a/Sources/Commands/PackageCommands/Update.swift b/Sources/Commands/PackageCommands/Update.swift index 1757da18657..b3b22736499 100644 --- a/Sources/Commands/PackageCommands/Update.swift +++ b/Sources/Commands/PackageCommands/Update.swift @@ -27,17 +27,19 @@ extension SwiftPackageCommand { @OptionGroup(visibility: .hidden) var globalOptions: GlobalOptions - - @Flag(name: [.long, .customShort("n")], - help: "Display the list of dependencies that can be updated.") + + @Flag( + name: [.long, .customShort("n")], + help: "Display the list of dependencies that can be updated." + ) var dryRun: Bool = false - + @Argument(help: "The packages to update.") var packages: [String] = [] - + func run(_ swiftCommandState: SwiftCommandState) async throws { let workspace = try swiftCommandState.getActiveWorkspace() - + let changes = try await workspace.updateDependencies( root: swiftCommandState.getWorkspaceRoot(), packages: packages, @@ -45,10 +47,10 @@ extension SwiftPackageCommand { observabilityScope: swiftCommandState.observabilityScope ) - if self.dryRun, let changes = changes, let resolvedPackagesStore = swiftCommandState.observabilityScope.trap({ try workspace.resolvedPackagesStore.load() }){ + if self.dryRun, let changes = changes, let resolvedPackagesStore = swiftCommandState.observabilityScope.trap({ try workspace.resolvedPackagesStore.load() }) { self.logPackageChanges(changes: changes, store: resolvedPackagesStore) } - + if !self.dryRun { // Throw if there were errors when loading the graph. // The actual errors will be printed before exiting. @@ -57,10 +59,10 @@ extension SwiftPackageCommand { } } } - + private func logPackageChanges(changes: [(PackageReference, Workspace.PackageStateChange)], store: ResolvedPackagesStore) { let changes = changes.filter { $0.1 != .unchanged } - + var report = "\(changes.count) dependenc\(changes.count == 1 ? "y has" : "ies have") changed\(changes.count > 0 ? ":" : ".")" for (package, change) in changes { let currentVersion = store.resolvedPackages[package.identity]?.state.description ?? "" @@ -78,7 +80,7 @@ extension SwiftPackageCommand { continue } } - + print(report) } } diff --git a/Sources/Commands/Snippets/CardStack.swift b/Sources/Commands/Snippets/CardStack.swift index 0c2616ec983..4e2bf1ae24f 100644 --- a/Sources/Commands/Snippets/CardStack.swift +++ b/Sources/Commands/Snippets/CardStack.swift @@ -63,12 +63,10 @@ struct CardStack { let isColorized: Bool = swiftCommandState.options.logging.colorDiagnostics if let prompt { - isColorized ? - print(brightBlack { prompt }.terminalString()) : - print(plain { prompt }.terminalString()) + isColorized ? print(brightBlack { prompt }.terminalString()) : print(plain { prompt }.terminalString()) } - isColorized ? - terminal.write(">>> ", inColor: .green, bold: true) + isColorized + ? terminal.write(">>> ", inColor: .green, bold: true) : terminal.write(">>> ", inColor: .noColor, bold: false) return readLine(strippingNewline: true) diff --git a/Sources/Commands/Snippets/Cards/SnippetCard.swift b/Sources/Commands/Snippets/Cards/SnippetCard.swift index e4fbe38b6d7..b601ae7be76 100644 --- a/Sources/Commands/Snippets/Cards/SnippetCard.swift +++ b/Sources/Commands/Snippets/Cards/SnippetCard.swift @@ -44,15 +44,16 @@ struct SnippetCard: Card { func render() -> String { let isColorized: Bool = swiftCommandState.options.logging.colorDiagnostics - var rendered = isColorized ? colorized { - brightYellow { - "# " - snippet.name - } - "\n\n" - }.terminalString() - : - plain { + var rendered = + isColorized + ? colorized { + brightYellow { + "# " + snippet.name + } + "\n\n" + }.terminalString() + : plain { plain { "# " snippet.name @@ -61,18 +62,20 @@ struct SnippetCard: Card { }.terminalString() if !snippet.explanation.isEmpty { - rendered += isColorized ? brightBlack { - snippet.explanation - .split(separator: "\n", omittingEmptySubsequences: false) - .map { "// " + $0 } - .joined(separator: "\n") - }.terminalString() - : plain { - snippet.explanation - .split(separator: "\n", omittingEmptySubsequences: false) - .map { "// " + $0 } - .joined(separator: "\n") - }.terminalString() + rendered += + isColorized + ? brightBlack { + snippet.explanation + .split(separator: "\n", omittingEmptySubsequences: false) + .map { "// " + $0 } + .joined(separator: "\n") + }.terminalString() + : plain { + snippet.explanation + .split(separator: "\n", omittingEmptySubsequences: false) + .map { "// " + $0 } + .joined(separator: "\n") + }.terminalString() rendered += "\n\n" } @@ -86,7 +89,7 @@ struct SnippetCard: Card { return "\nRun this snippet? [R: run, or press Enter to return]" } - func acceptLineInput(_ line: S) async -> CardEvent? where S : StringProtocol { + func acceptLineInput(_ line: S) async -> CardEvent? where S: StringProtocol { let trimmed = line.drop { $0.isWhitespace }.prefix { !$0.isWhitespace }.lowercased() guard !trimmed.isEmpty else { return .pop() diff --git a/Sources/Commands/Snippets/Cards/SnippetGroupCard.swift b/Sources/Commands/Snippets/Cards/SnippetGroupCard.swift index 1a27442a5c9..bfacaaa17f9 100644 --- a/Sources/Commands/Snippets/Cards/SnippetGroupCard.swift +++ b/Sources/Commands/Snippets/Cards/SnippetGroupCard.swift @@ -31,7 +31,7 @@ struct SnippetGroupCard: Card { """ } - func acceptLineInput(_ line: S) -> CardEvent? where S : StringProtocol { + func acceptLineInput(_ line: S) -> CardEvent? where S: StringProtocol { if line.isEmpty || line.allSatisfy({ $0.isWhitespace }) { return .pop() } @@ -39,7 +39,8 @@ struct SnippetGroupCard: Card { return .quit() } if let index = Int(line), - snippetGroup.snippets.indices.contains(index) { + snippetGroup.snippets.indices.contains(index) + { return .push(SnippetCard(snippet: snippetGroup.snippets[index], number: index, swiftCommandState: swiftCommandState)) } else if let foundSnippetIndex = snippetGroup.snippets.firstIndex(where: { $0.name == line }) { return .push(SnippetCard(snippet: snippetGroup.snippets[foundSnippetIndex], number: foundSnippetIndex, swiftCommandState: swiftCommandState)) @@ -53,14 +54,16 @@ struct SnippetGroupCard: Card { let isColorized = swiftCommandState.options.logging.colorDiagnostics precondition(!snippetGroup.snippets.isEmpty) - var rendered = isColorized ? brightYellow { - """ - # \(snippetGroup.name) + var rendered = + isColorized + ? brightYellow { + """ + # \(snippetGroup.name) - """ - }.terminalString() : - plain { + """ + }.terminalString() + : plain { """ # \(snippetGroup.name) @@ -77,13 +80,14 @@ struct SnippetGroupCard: Card { .enumerated() .map { pair -> String in let (number, snippet) = pair - return isColorized ? brightCyan { - "\(number). \(snippet.name)\n" - plain { - snippet.explanation.spm_multilineIndent(count: 3) - } - }.terminalString() : - plain { + return isColorized + ? brightCyan { + "\(number). \(snippet.name)\n" + plain { + snippet.explanation.spm_multilineIndent(count: 3) + } + }.terminalString() + : plain { "\(number). \(snippet.name)\n" plain { snippet.explanation.spm_multilineIndent(count: 3) diff --git a/Sources/Commands/Snippets/Cards/TopCard.swift b/Sources/Commands/Snippets/Cards/TopCard.swift index 614a20b6080..155ed4de89a 100644 --- a/Sources/Commands/Snippets/Cards/TopCard.swift +++ b/Sources/Commands/Snippets/Cards/TopCard.swift @@ -61,11 +61,13 @@ struct TopCard: Card { return "" } - var rendered = isColorized ? brightCyan { - "\n## Products" - "\n\n" - }.terminalString() : - plain { + var rendered = + isColorized + ? brightCyan { + "\n## Products" + "\n\n" + }.terminalString() + : plain { "\n## Products" "\n\n" }.terminalString() @@ -84,18 +86,19 @@ struct TopCard: Card { let (number, snippetGroup) = pair let snippetNoun = snippetGroup.snippets.count > 1 ? "snippets" : "snippet" let heading = "\(number). \(snippetGroup.name) (\(snippetGroup.snippets.count) \(snippetNoun))" - return isColorized ? colorized { - cyan { - heading - "\n" - } - if !snippetGroup.explanation.isEmpty { - """ - \(snippetGroup.explanation.spm_multilineIndent(count: 3)) - """ - } - }.terminalString() : - plain { + return isColorized + ? colorized { + cyan { + heading + "\n" + } + if !snippetGroup.explanation.isEmpty { + """ + \(snippetGroup.explanation.spm_multilineIndent(count: 3)) + """ + } + }.terminalString() + : plain { plain { heading "\n" @@ -108,15 +111,16 @@ struct TopCard: Card { }.terminalString() } - return isColorized ? colorized { - brightCyan { - "\n## Snippets" - } - "\n\n" - snippetPreviews.joined(separator: "\n\n") - "\n" - }.terminalString() : - plain { + return isColorized + ? colorized { + brightCyan { + "\n## Snippets" + } + "\n\n" + snippetPreviews.joined(separator: "\n\n") + "\n" + }.terminalString() + : plain { plain { "\n## Snippets" } @@ -128,22 +132,25 @@ struct TopCard: Card { func render() -> String { let isColorized: Bool = self.swiftCommandState.options.logging.colorDiagnostics - let heading = isColorized ? brightYellow { - "# " - package.identity.description - } : plain { - "# " - package.identity.description - } + let heading = + isColorized + ? brightYellow { + "# " + package.identity.description + } + : plain { + "# " + package.identity.description + } return """ - \(heading) - \(renderProducts()) - \(renderSnippets()) - """ + \(heading) + \(renderProducts()) + \(renderSnippets()) + """ } - func acceptLineInput(_ line: S) -> CardEvent? where S : StringProtocol { + func acceptLineInput(_ line: S) -> CardEvent? where S: StringProtocol { guard !line.isEmpty else { print("\u{0007}") return nil @@ -152,7 +159,8 @@ struct TopCard: Card { return .quit() } if let index = Int(line), - snippetGroups.indices.contains(index) { + snippetGroups.indices.contains(index) + { return .push(SnippetGroupCard(snippetGroup: snippetGroups[index], swiftCommandState: swiftCommandState)) } else if let groupByName = snippetGroups.first(where: { $0.name == line }) { return .push(SnippetGroupCard(snippetGroup: groupByName, swiftCommandState: swiftCommandState)) diff --git a/Sources/Commands/Snippets/Colorful.swift b/Sources/Commands/Snippets/Colorful.swift index b90f02e896d..1e1ef3f5d56 100644 --- a/Sources/Commands/Snippets/Colorful.swift +++ b/Sources/Commands/Snippets/Colorful.swift @@ -110,7 +110,7 @@ enum Color4: String, Color { return .brightRed case .green: return .brightGreen - case .yellow : + case .yellow: return .brightYellow case .blue: return .brightBlue diff --git a/Sources/Commands/SwiftBuildCommand.swift b/Sources/Commands/SwiftBuildCommand.swift index 5c366090224..cb1cc951d01 100644 --- a/Sources/Commands/SwiftBuildCommand.swift +++ b/Sources/Commands/SwiftBuildCommand.swift @@ -15,8 +15,7 @@ import Basics import Build -@_spi(SwiftPMInternal) -import CoreCommands +@_spi(SwiftPMInternal) import CoreCommands import PackageGraph @@ -64,7 +63,7 @@ struct BuildCommandOptions: ParsableArguments { } guard allSubsets.count < 2 else { - observabilityScope.emit(.mutuallyExclusiveArgumentsError(arguments: allSubsets.map{ $0.argumentName })) + observabilityScope.emit(.mutuallyExclusiveArgumentsError(arguments: allSubsets.map { $0.argumentName })) return nil } @@ -76,9 +75,11 @@ struct BuildCommandOptions: ParsableArguments { var buildTests: Bool = false /// Whether to enable code coverage. - @Flag(name: .customLong("code-coverage"), - inversion: .prefixedEnableDisable, - help: "Enable code coverage.") + @Flag( + name: .customLong("code-coverage"), + inversion: .prefixedEnableDisable, + help: "Enable code coverage." + ) var enableCodeCoverage: Bool = false /// If the binary output path should be printed. @@ -86,13 +87,17 @@ struct BuildCommandOptions: ParsableArguments { var shouldPrintBinPath: Bool = false /// Whether to output a graphviz file visualization of the combined job graph for all targets - @Flag(name: .customLong("print-manifest-job-graph"), - help: "Write the command graph for the build manifest as a Graphviz file.") + @Flag( + name: .customLong("print-manifest-job-graph"), + help: "Write the command graph for the build manifest as a Graphviz file." + ) var printManifestGraphviz: Bool = false /// Whether to output a graphviz file visualization of the PIF JSON sent to Swift Build. - @Flag(name: .customLong("print-pif-manifest-graph"), - help: "Write the PIF JSON sent to Swift Build as a Graphviz file.") + @Flag( + name: .customLong("print-pif-manifest-graph"), + help: "Write the PIF JSON sent to Swift Build as a Graphviz file." + ) var printPIFManifestGraphviz: Bool = false /// Specific target to build. @@ -123,7 +128,8 @@ public struct SwiftBuildCommand: AsyncSwiftCommand { abstract: "Build sources into binary products.", discussion: "SEE ALSO: swift run, swift package, swift test", version: SwiftVersion.current.completeDisplayString, - helpNames: [.short, .long, .customLong("help", withSingleDash: true)]) + helpNames: [.short, .long, .customLong("help", withSingleDash: true)] + ) @OptionGroup() public var globalOptions: GlobalOptions @@ -138,9 +144,11 @@ public struct SwiftBuildCommand: AsyncSwiftCommand { if options.printManifestGraphviz { // FIXME: Doesn't seem ideal that we need an explicit build operation, but this concretely uses the `LLBuildManifest`. - guard let buildOperation = try await swiftCommandState.createBuildSystem( - explicitBuildSystem: .native, - ) as? BuildOperation else { + guard + let buildOperation = try await swiftCommandState.createBuildSystem( + explicitBuildSystem: .native, + ) as? BuildOperation + else { throw StringError("asked for native build system but did not get it") } let buildManifest = try await buildOperation.getBuildManifest() @@ -163,12 +171,12 @@ public struct SwiftBuildCommand: AsyncSwiftCommand { productsBuildParameters.testingParameters.enableCodeCoverage = true toolsBuildParameters.testingParameters.enableCodeCoverage = true } - + if self.options.printPIFManifestGraphviz { productsBuildParameters.printPIFManifestGraphviz = true toolsBuildParameters.printPIFManifestGraphviz = true } - + do { try await build( swiftCommandState, diff --git a/Sources/Commands/SwiftRunCommand.swift b/Sources/Commands/SwiftRunCommand.swift index 1b6d7448214..6130be65a29 100644 --- a/Sources/Commands/SwiftRunCommand.swift +++ b/Sources/Commands/SwiftRunCommand.swift @@ -24,7 +24,7 @@ import func TSCBasic.exec import enum TSCUtility.Diagnostics #if canImport(Android) -import Android + import Android #endif /// An enumeration of the errors that can be generated by the run tool. @@ -89,8 +89,10 @@ struct RunCommandOptions: ParsableArguments { var executable: String? /// The arguments to pass to the executable. - @Argument(parsing: .captureForPassthrough, - help: "The arguments to pass to the executable.") + @Argument( + parsing: .captureForPassthrough, + help: "The arguments to pass to the executable." + ) var arguments: [String] = [] } @@ -102,7 +104,8 @@ public struct SwiftRunCommand: AsyncSwiftCommand { abstract: "Build and run an executable product.", discussion: "SEE ALSO: swift build, swift package, swift test", version: SwiftVersion.current.completeDisplayString, - helpNames: [.short, .long, .customLong("help", withSingleDash: true)]) + helpNames: [.short, .long, .customLong("help", withSingleDash: true)] + ) @OptionGroup() public var globalOptions: GlobalOptions @@ -117,7 +120,7 @@ public struct SwiftRunCommand: AsyncSwiftCommand { public func run(_ swiftCommandState: SwiftCommandState) async throws { if options.shouldBuildTests && options.shouldSkipBuild { swiftCommandState.observabilityScope.emit( - .mutuallyExclusiveArgumentsError(arguments: ["--build-tests", "--skip-build"]) + .mutuallyExclusiveArgumentsError(arguments: ["--build-tests", "--skip-build"]) ) throw ExitCode.failure } @@ -178,7 +181,8 @@ public struct SwiftRunCommand: AsyncSwiftCommand { } if let debugger = try swiftCommandState.getTargetToolchain().swiftSDK.toolset.knownTools[.debugger], - let debuggerPath = debugger.path { + let debuggerPath = debugger.path + { try self.run( fileSystem: swiftCommandState.fileSystem, executablePath: debuggerPath, @@ -233,7 +237,8 @@ public struct SwiftRunCommand: AsyncSwiftCommand { let arguments: [String] if let debugger = try swiftCommandState.getTargetToolchain().swiftSDK.toolset.knownTools[.debugger], - let debuggerPath = debugger.path { + let debuggerPath = debugger.path + { runnerPath = debuggerPath arguments = debugger.extraCLIOptions + [productAbsolutePath.pathString] + options.arguments } else { @@ -262,7 +267,7 @@ public struct SwiftRunCommand: AsyncSwiftCommand { // There should be only one product with the given name in the graph // and it should be executable or snippet. guard let product = graph.product(for: executable), - product.type == .executable || product.type == .snippet + product.type == .executable || product.type == .snippet else { throw RunError.executableNotFound(executable) } @@ -329,33 +334,33 @@ public struct SwiftRunCommand: AsyncSwiftCommand { /// A safe wrapper of TSCBasic.exec. private func execute(path: String, args: [String]) throws -> Never { #if !os(Windows) - // Dispatch will disable almost all asynchronous signals on its worker threads, and this is called from `async` - // context. To correctly `exec` a freshly built binary, we will need to: - // 1. reset the signal masks - for i in 1...' \ - or './'. - """) + @Option( + help: """ + Run test cases that match a regular expression, Format: '.' \ + or './'. + """ + ) var filter: [String] = [] - @Option(name: .customLong("skip"), - help: "Skip test cases that match a regular expression, Example: '--skip PerformanceTests'.") + @Option( + name: .customLong("skip"), + help: "Skip test cases that match a regular expression, Example: '--skip PerformanceTests'." + ) var _testCaseSkip: [String] = [] /// Path where the xUnit xml file should be generated. - @Option(name: .customLong("xunit-output"), - help: "Path where the xUnit xml file should be generated.") + @Option( + name: .customLong("xunit-output"), + help: "Path where the xUnit xml file should be generated." + ) var xUnitOutput: AbsolutePath? @Flag( @@ -218,9 +247,11 @@ struct TestCommandOptions: ParsableArguments { var enableTestableImports: Bool = true /// Whether to enable code coverage. - @Flag(name: .customLong("code-coverage"), - inversion: .prefixedEnableDisable, - help: "Enable code coverage.") + @Flag( + name: .customLong("code-coverage"), + inversion: .prefixedEnableDisable, + help: "Enable code coverage." + ) var enableCodeCoverage: Bool = false /// Configure test output. @@ -268,9 +299,10 @@ public struct SwiftTestCommand: AsyncSwiftCommand { discussion: "SEE ALSO: swift build, swift run, swift package", version: SwiftVersion.current.completeDisplayString, subcommands: [ - List.self, Last.self + List.self, Last.self, ], - helpNames: [.short, .long, .customLong("help", withSingleDash: true)]) + helpNames: [.short, .long, .customLong("help", withSingleDash: true)] + ) public var globalOptions: GlobalOptions { options.globalOptions @@ -326,7 +358,8 @@ public struct SwiftTestCommand: AsyncSwiftCommand { experimentalTestOutput: options.enableExperimentalTestOutput, sanitizers: globalOptions.build.sanitizers ) - let tests = try testSuites + let tests = + try testSuites .filteredTests(specifier: options.testCaseSpecifier) .skippedTests(specifier: options.skippedTests(fileSystem: swiftCommandState.fileSystem)) @@ -417,7 +450,8 @@ public struct SwiftTestCommand: AsyncSwiftCommand { experimentalTestOutput: options.enableExperimentalTestOutput, sanitizers: globalOptions.build.sanitizers ) - let tests = try testSuites + let tests = + try testSuites .filteredTests(specifier: options.testCaseSpecifier) .skippedTests(specifier: options.skippedTests(fileSystem: swiftCommandState.fileSystem)) @@ -526,12 +560,13 @@ public struct SwiftTestCommand: AsyncSwiftCommand { library: library ) - let runnerPaths: [AbsolutePath] = switch library { - case .xctest: - testProducts.map(\.bundlePath) - case .swiftTesting: - testProducts.map(\.binaryPath) - } + let runnerPaths: [AbsolutePath] = + switch library { + case .xctest: + testProducts.map(\.bundlePath) + case .swiftTesting: + testProducts.map(\.binaryPath) + } let runner = TestRunner( bundlePaths: runnerPaths, @@ -642,18 +677,20 @@ public struct SwiftTestCommand: AsyncSwiftCommand { // Export using the llvm-cov tool. let llvmCov = try swiftCommandState.getTargetToolchain().getLLVMCov() let (productsBuildParameters, _) = try swiftCommandState.buildParametersForTest(options: self.options) - let archArgs: [String] = if let arch = productsBuildParameters.triple.llvmCovArchArgument { - ["--arch", "\(arch)"] - } else { - [] - } - let args = [ - llvmCov.pathString, - "export", - "-instr-profile=\(productsBuildParameters.codeCovDataFile)", - ] + archArgs + [ - testBinary.pathString, - ] + let archArgs: [String] = + if let arch = productsBuildParameters.triple.llvmCovArchArgument { + ["--arch", "\(arch)"] + } else { + [] + } + let args = + [ + llvmCov.pathString, + "export", + "-instr-profile=\(productsBuildParameters.codeCovDataFile)", + ] + archArgs + [ + testBinary.pathString + ] let result = try await AsyncProcess.popen(arguments: args) if result.exitStatus != .terminated(code: 0) { @@ -748,7 +785,7 @@ extension SwiftTestCommand { func run(_ swiftCommandState: SwiftCommandState) throws { try SwiftTestCommand.handleTestOutput( productsBuildParameters: try swiftCommandState.productsBuildParameters, - packagePath: localFileSystem.currentWorkingDirectory ?? .root // by definition runs in the current working directory + packagePath: localFileSystem.currentWorkingDirectory ?? .root // by definition runs in the current working directory ) } } @@ -781,7 +818,9 @@ extension SwiftTestCommand { try await self.runCommand(swiftCommandState) } catch let error as FileSystemError { if sharedOptions.shouldSkipBuilding { - throw ErrorWithContext(error, """ + throw ErrorWithContext( + error, + """ Test build artifacts were not found in the build folder. The `--skip-build` flag was provided; either build the tests first with \ `swift build --build tests` or rerun the `swift test list` command without \ @@ -934,11 +973,11 @@ final class TestRunner { testSpecifier = testSpecifiers.joined(separator: ",") } -#if os(macOS) - return ["-XCTest", testSpecifier] -#else - return [testSpecifier] -#endif + #if os(macOS) + return ["-XCTest", testSpecifier] + #else + return [testSpecifier] + #endif } /// Creates an instance of TestRunner. @@ -999,23 +1038,23 @@ final class TestRunner { args.append(testPath.relative(to: localFileSystem.currentWorkingDirectory!).pathString) args.append(contentsOf: self.additionalArguments) } else { -#if os(macOS) - switch library { - case .xctest: - guard let xctestPath = self.toolchain.xctestPath else { - throw TestError.xcodeNotInstalled + #if os(macOS) + switch library { + case .xctest: + guard let xctestPath = self.toolchain.xctestPath else { + throw TestError.xcodeNotInstalled + } + args += [xctestPath.pathString] + case .swiftTesting: + let helper = try self.toolchain.getSwiftTestingHelper() + args += [helper.pathString, "--test-bundle-path", testPath.pathString] } - args += [xctestPath.pathString] - case .swiftTesting: - let helper = try self.toolchain.getSwiftTestingHelper() - args += [helper.pathString, "--test-bundle-path", testPath.pathString] - } - args += self.additionalArguments - args += [testPath.pathString] - #else - args += [testPath.pathString] - args += self.additionalArguments - #endif + args += self.additionalArguments + args += [testPath.pathString] + #else + args += [testPath.pathString] + args += self.additionalArguments + #endif } if library == .swiftTesting { @@ -1042,7 +1081,7 @@ final class TestRunner { ) let process = AsyncProcess(arguments: try args(forTestAt: path), environment: self.testEnv, outputRedirection: outputRedirection) guard let terminationKey = self.cancellator.register(process) else { - return .failure // terminating + return .failure // terminating } defer { self.cancellator.deregister(terminationKey) } try process.launch() @@ -1053,9 +1092,9 @@ final class TestRunner { case .terminated(code: EXIT_NO_TESTS_FOUND) where library == .swiftTesting: return .noMatchingTests #if !os(Windows) - case .signalled(let signal) where ![SIGINT, SIGKILL, SIGTERM].contains(signal): - testObservabilityScope.emit(error: "Exited with unexpected signal code \(signal)") - return .failure + case .signalled(let signal) where ![SIGINT, SIGKILL, SIGTERM].contains(signal): + testObservabilityScope.emit(error: "Exited with unexpected signal code \(signal)") + return .failure #endif default: return .failure @@ -1193,7 +1232,7 @@ final class ParallelTestRunner { toolchain: self.toolchain, destinationBuildParameters: self.productsBuildParameters, sanitizers: self.buildOptions.sanitizers, - library: .xctest // swift-testing does not use ParallelTestRunner + library: .xctest // swift-testing does not use ParallelTestRunner ) // Enqueue all the tests. @@ -1212,22 +1251,24 @@ final class ParallelTestRunner { toolchain: self.toolchain, testEnv: testEnv, observabilityScope: self.observabilityScope, - library: .xctest // swift-testing does not use ParallelTestRunner + library: .xctest // swift-testing does not use ParallelTestRunner ) var output = "" let outputLock = NSLock() let start = DispatchTime.now() - let result = testRunner.test(outputHandler: { _output in outputLock.withLock{ output += _output }}) + let result = testRunner.test(outputHandler: { _output in outputLock.withLock { output += _output } }) let duration = start.distance(to: .now()) if result == .failure { self.ranSuccessfully = false } - self.finishedTests.enqueue(TestResult( - unitTest: test, - output: output, - success: result != .failure, - duration: duration - )) + self.finishedTests.enqueue( + TestResult( + unitTest: test, + output: output, + success: result != .failure, + duration: duration + ) + ) } } thread.start() @@ -1317,26 +1358,30 @@ struct TestSuite { /// - Returns: Array of TestSuite. static func parse(json: JSON, context: String) throws -> [TestSuite] { guard case let .dictionary(contents) = json, - case let .array(testSuites)? = contents["tests"] else { + case let .array(testSuites)? = contents["tests"] + else { throw TestError.invalidListTestJSONData(context: context) } return try testSuites.map({ testSuite in guard case let .dictionary(testSuiteData) = testSuite, - case let .string(name)? = testSuiteData["name"], - case let .array(allTestsData)? = testSuiteData["tests"] else { + case let .string(name)? = testSuiteData["name"], + case let .array(allTestsData)? = testSuiteData["tests"] + else { throw TestError.invalidListTestJSONData(context: context) } let testCases: [TestSuite.TestCase] = try allTestsData.map({ testCase in guard case let .dictionary(testCaseData) = testCase, - case let .string(name)? = testCaseData["name"], - case let .array(tests)? = testCaseData["tests"] else { + case let .string(name)? = testCaseData["name"], + case let .array(tests)? = testCaseData["tests"] + else { throw TestError.invalidListTestJSONData(context: context) } let testMethods: [String] = try tests.map({ test in guard case let .dictionary(testData) = test, - case let .string(testMethod)? = testData["name"] else { + case let .string(testMethod)? = testData["name"] + else { throw TestError.invalidListTestJSONData(context: context) } return testMethod @@ -1373,12 +1418,14 @@ fileprivate extension Dictionary where Key == AbsolutePath, Value == [TestSuite] case .regex(let patterns): return allTests.filter({ test in patterns.contains { pattern in - test.specifier.range(of: pattern, - options: .regularExpression) != nil + test.specifier.range( + of: pattern, + options: .regularExpression + ) != nil } }) case .specific(let name): - return allTests.filter{ $0.specifier == name } + return allTests.filter { $0.specifier == name } case .skip: throw InternalError("Tests to skip should never have been passed here.") } @@ -1394,7 +1441,7 @@ fileprivate extension Array where Element == UnitTest { case .skip(let skippedTests): var result = self for skippedTest in skippedTests { - result = result.filter{ + result = result.filter { $0.specifier.range(of: skippedTest, options: .regularExpression) == nil } } @@ -1489,12 +1536,12 @@ private func _escapeForXML(_ character: Character) -> String { case "&": "&" case _ where !character.isASCII || character.isNewline: - character.unicodeScalars.lazy - .map(\.value) - .map { "&#\($0);" } - .joined() + character.unicodeScalars.lazy + .map(\.value) + .map { "&#\($0);" } + .joined() default: - String(character) + String(character) } } @@ -1568,14 +1615,14 @@ private extension Basics.Diagnostic { /// it duplicates the definition of this constant in its own source. Any changes /// to this constant in either package must be mirrored in the other. private var EXIT_NO_TESTS_FOUND: CInt { -#if os(macOS) || os(Linux) || canImport(Android) || os(FreeBSD) - EX_UNAVAILABLE -#elseif os(Windows) - ERROR_NOT_FOUND -#else -#warning("Platform-specific implementation missing: value for EXIT_NO_TESTS_FOUND unavailable") - return 2 // We're assuming that EXIT_SUCCESS = 0 and EXIT_FAILURE = 1. -#endif + #if os(macOS) || os(Linux) || canImport(Android) || os(FreeBSD) + EX_UNAVAILABLE + #elseif os(Windows) + ERROR_NOT_FOUND + #else + #warning("Platform-specific implementation missing: value for EXIT_NO_TESTS_FOUND unavailable") + return 2 // We're assuming that EXIT_SUCCESS = 0 and EXIT_FAILURE = 1. + #endif } /// Builds the "test" target if enabled in options. @@ -1593,11 +1640,12 @@ private func buildTestsIfNeeded( toolsBuildParameters: toolsBuildParameters ) - let subset: BuildSubset = if let testProduct { - .product(testProduct) - } else { - .allIncludingTests - } + let subset: BuildSubset = + if let testProduct { + .product(testProduct) + } else { + .allIncludingTests + } try await buildSystem.build(subset: subset, buildOutputs: []) diff --git a/Sources/Commands/Utilities/APIDigester.swift b/Sources/Commands/Utilities/APIDigester.swift index 85f3dab6e03..ad0d2cfe515 100644 --- a/Sources/Commands/Utilities/APIDigester.swift +++ b/Sources/Commands/Utilities/APIDigester.swift @@ -79,7 +79,7 @@ struct APIDigesterBaselineDumper { var modulesToDiff = modulesToDiff let apiDiffDir = productsBuildParameters.apiDiff let baselineDir = (baselineDir ?? apiDiffDir).appending(component: baselineRevision.identifier) - let baselinePath: (String)->AbsolutePath = { module in + let baselinePath: (String) -> AbsolutePath = { module in baselineDir.appending(component: module + ".json") } @@ -215,8 +215,8 @@ public struct SwiftAPIDigester { } try self.fileSystem.readFileContents(outputPath).withData { data in - if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] { - guard let abiRoot = jsonObject["ABIRoot"] as? [String:Any] else { + if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { + guard let abiRoot = jsonObject["ABIRoot"] as? [String: Any] else { throw Error.failedToValidateBaseline(module: module) } @@ -238,7 +238,7 @@ public struct SwiftAPIDigester { var args = [ "-diagnose-sdk", "-baseline-path", baselinePath.pathString, - "-module", module + "-module", module, ] args.append(contentsOf: try buildPlan.createAPIToolCommonArgs(includeLibrarySearchPaths: false)) if let breakageAllowlistPath { @@ -256,9 +256,11 @@ public struct SwiftAPIDigester { let apiDigesterCategory = "api-digester-breaking-change" let apiBreakingChanges = serializedDiagnostics.diagnostics.filter { $0.category == apiDigesterCategory } let otherDiagnostics = serializedDiagnostics.diagnostics.filter { $0.category != apiDigesterCategory } - return ComparisonResult(moduleName: module, - apiBreakingChanges: apiBreakingChanges, - otherDiagnostics: otherDiagnostics) + return ComparisonResult( + moduleName: module, + apiBreakingChanges: apiBreakingChanges, + otherDiagnostics: otherDiagnostics + ) } } diff --git a/Sources/Commands/Utilities/DOTManifestSerializer.swift b/Sources/Commands/Utilities/DOTManifestSerializer.swift index 448b41643d1..f78beba966d 100644 --- a/Sources/Commands/Utilities/DOTManifestSerializer.swift +++ b/Sources/Commands/Utilities/DOTManifestSerializer.swift @@ -38,8 +38,9 @@ struct DOTManifestSerializer { /// Quote the name and escape the quotes and backslashes. func quoteName(_ name: String) -> String { - "\"" + name.replacing("\"", with: "\\\"") - .replacing("\\", with: "\\\\") + "\"" + "\"" + + name.replacing("\"", with: "\\\"") + .replacing("\\", with: "\\\\") + "\"" } mutating func writeDOT(to stream: OutputByteStream) { diff --git a/Sources/Commands/Utilities/DependenciesSerializer.swift b/Sources/Commands/Utilities/DependenciesSerializer.swift index 31f82582013..4f607ee09c3 100644 --- a/Sources/Commands/Utilities/DependenciesSerializer.swift +++ b/Sources/Commands/Utilities/DependenciesSerializer.swift @@ -44,7 +44,7 @@ final class PlainTextDumper: DependenciesDumper { stream.send("\(hanger)\(package.identity.description)<\(package.manifest.packageLocation)@\(pkgVersion)>\(traitsEnabled)\n") if !package.dependencies.isEmpty { - let replacement = (index == packages.count - 1) ? " " : "│ " + let replacement = (index == packages.count - 1) ? " " : "│ " var childPrefix = hanger let startIndex = childPrefix.index(childPrefix.endIndex, offsetBy: -4) childPrefix.replaceSubrange(startIndex.. JSON { return .orderedDictionary([ "identity": .string(package.identity.description), - "name": .string(package.manifest.displayName), // TODO: remove? + "name": .string(package.manifest.displayName), // TODO: remove? "url": .string(package.manifest.packageLocation), "version": .string(package.manifest.version?.description ?? "unspecified"), "path": .string(package.path.pathString), diff --git a/Sources/Commands/Utilities/DescribedPackage.swift b/Sources/Commands/Utilities/DescribedPackage.swift index ab9a72f411c..5e887e4f0c5 100644 --- a/Sources/Commands/Utilities/DescribedPackage.swift +++ b/Sources/Commands/Utilities/DescribedPackage.swift @@ -20,7 +20,7 @@ import func TSCBasic.transitiveClosure /// Represents a package for the sole purpose of generating a description. struct DescribedPackage: Encodable { - let name: String // for backwards compatibility + let name: String // for backwards compatibility let manifestDisplayName: String let path: String let toolsVersion: String @@ -35,15 +35,16 @@ struct DescribedPackage: Encodable { init(from package: Package) { self.manifestDisplayName = package.manifest.displayName - self.name = self.manifestDisplayName // TODO: deprecate, backwards compatibility 11/2021 + self.name = self.manifestDisplayName // TODO: deprecate, backwards compatibility 11/2021 self.path = package.path.pathString - self.toolsVersion = "\(package.manifest.toolsVersion.major).\(package.manifest.toolsVersion.minor)" - + (package.manifest.toolsVersion.patch == 0 ? "" : ".\(package.manifest.toolsVersion.patch)") + self.toolsVersion = + "\(package.manifest.toolsVersion.major).\(package.manifest.toolsVersion.minor)" + + (package.manifest.toolsVersion.patch == 0 ? "" : ".\(package.manifest.toolsVersion.patch)") self.dependencies = package.manifest.dependencies.map { DescribedPackageDependency(from: $0) } self.defaultLocalization = package.manifest.defaultLocalization self.platforms = package.manifest.platforms.map { DescribedPlatformRestriction(from: $0) } // SwiftPM considers tests to be products, which is not how things are presented in the manifest. - let nonTestProducts = package.products.filter{ $0.type != .test } + let nonTestProducts = package.products.filter { $0.type != .test } self.products = nonTestProducts.map { DescribedProduct(from: $0, in: package) } @@ -51,33 +52,36 @@ struct DescribedPackage: Encodable { // contributions that occur through `.product()` dependencies, but since those targets are still part of a // product of the package, the set of targets that contribute to products still accurately represents the // set of targets reachable from external clients. - let targetProductPairs = nonTestProducts.flatMap{ p in - transitiveClosure(p.modules, successors: { - $0.dependencies.compactMap{ $0.module } - }).union(p.modules).map{ t in (t, p) } + let targetProductPairs = nonTestProducts.flatMap { p in + transitiveClosure( + p.modules, + successors: { + $0.dependencies.compactMap { $0.module } + } + ).union(p.modules).map { t in (t, p) } } - let targetsToProducts = Dictionary(targetProductPairs.map{ ($0.0, [$0.1]) }, uniquingKeysWith: { $0 + $1 }) + let targetsToProducts = Dictionary(targetProductPairs.map { ($0.0, [$0.1]) }, uniquingKeysWith: { $0 + $1 }) self.targets = package.modules.map { - return DescribedTarget(from: $0, in: package, productMemberships: targetsToProducts[$0]?.map{ $0.name }) + return DescribedTarget(from: $0, in: package, productMemberships: targetsToProducts[$0]?.map { $0.name }) } self.cLanguageStandard = package.manifest.cLanguageStandard self.cxxLanguageStandard = package.manifest.cxxLanguageStandard - self.swiftLanguagesVersions = package.manifest.swiftLanguageVersions?.map{ $0.description } + self.swiftLanguagesVersions = package.manifest.swiftLanguageVersions?.map { $0.description } } - + /// Represents a platform restriction for the sole purpose of generating a description. struct DescribedPlatformRestriction: Encodable { let name: String let version: String let options: [String]? - + init(from platform: PlatformDescription) { self.name = platform.platformName self.version = platform.version self.options = platform.options.isEmpty ? nil : platform.options } } - + /// Represents a package dependency for the sole purpose of generating a description. enum DescribedPackageDependency: Encodable { case fileSystem(identity: PackageIdentity, path: AbsolutePath) @@ -162,15 +166,15 @@ struct DescribedPackage: Encodable { case .command(let intent, let permissions): self.type = "command" self.intent = .init(from: intent) - self.permissions = permissions.map{ .init(from: $0) } + self.permissions = permissions.map { .init(from: $0) } } } - + struct CommandIntent: Encodable { let type: String let verb: String? let description: String? - + init(from intent: PackageModel.PluginCommandIntent) { switch intent { case .documentationGeneration: @@ -211,7 +215,7 @@ struct DescribedPackage: Encodable { let type: String let reason: String let networkScope: NetworkScope - + init(from permission: PackageModel.PluginPermission) { switch permission { case .writeToPackageDirectory(let reason): @@ -240,20 +244,20 @@ struct DescribedPackage: Encodable { let targetDependencies: [String]? let productDependencies: [String]? let productMemberships: [String]? - + init(from target: Module, in package: Package, productMemberships: [String]?) { self.name = target.name self.type = target.type.rawValue self.c99name = target.c99name self.moduleType = Swift.type(of: target).typeDescription - self.pluginCapability = (target as? PluginModule).map{ DescribedPluginCapability(from: $0.capability, in: package) } + self.pluginCapability = (target as? PluginModule).map { DescribedPluginCapability(from: $0.capability, in: package) } self.path = target.sources.root.relative(to: package.path).pathString - self.sources = target.sources.relativePaths.map{ $0.pathString } + self.sources = target.sources.relativePaths.map { $0.pathString } self.resources = target.resources.isEmpty ? nil : target.resources - let targetDependencies = target.dependencies.compactMap{ $0.module } - self.targetDependencies = targetDependencies.isEmpty ? nil : targetDependencies.map{ $0.name } - let productDependencies = target.dependencies.compactMap{ $0.product } - self.productDependencies = productDependencies.isEmpty ? nil : productDependencies.map{ $0.name } + let targetDependencies = target.dependencies.compactMap { $0.module } + self.targetDependencies = targetDependencies.isEmpty ? nil : targetDependencies.map { $0.name } + let productDependencies = target.dependencies.compactMap { $0.product } + self.productDependencies = productDependencies.isEmpty ? nil : productDependencies.map { $0.name } self.productMemberships = productMemberships } } diff --git a/Sources/Commands/Utilities/MermaidPackageSerializer.swift b/Sources/Commands/Utilities/MermaidPackageSerializer.swift index 0e1923b1ffa..3ce7b04934d 100644 --- a/Sources/Commands/Utilities/MermaidPackageSerializer.swift +++ b/Sources/Commands/Utilities/MermaidPackageSerializer.swift @@ -22,7 +22,7 @@ struct MermaidPackageSerializer { var renderedMarkdown: String { var subgraphs = OrderedDictionary() subgraphs[package.identity.description] = package.products.productTargetEdges - + for edge in package.modules.targetDependencyEdges { if let subgraph = edge.to.subgraph { subgraphs[subgraph, default: []].append(edge) @@ -32,9 +32,9 @@ struct MermaidPackageSerializer { } return """ - ```mermaid - flowchart TB - \( + ```mermaid + flowchart TB + \( shouldIncludeLegend ? """ subgraph legend @@ -55,9 +55,9 @@ struct MermaidPackageSerializer { """ }.joined(separator: "\n\n ") ) - ``` + ``` - """ + """ } fileprivate struct Node { @@ -162,4 +162,3 @@ extension [Module] { } } } - diff --git a/Sources/Commands/Utilities/MultiRootSupport.swift b/Sources/Commands/Utilities/MultiRootSupport.swift index 7cd42e877bc..a5fba4cf2a1 100644 --- a/Sources/Commands/Utilities/MultiRootSupport.swift +++ b/Sources/Commands/Utilities/MultiRootSupport.swift @@ -16,7 +16,7 @@ import Foundation import TSCBasic #if canImport(FoundationXML) -import FoundationXML + import FoundationXML #endif import class PackageModel.Manifest @@ -93,7 +93,7 @@ public struct XcodeWorkspaceLoader: WorkspaceLoader { didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, - attributes attributeDict: [String : String] = [:] + attributes attributeDict: [String: String] = [:] ) { guard elementName == "FileRef" else { return } guard let location = attributeDict["location"] else { return } diff --git a/Sources/Commands/Utilities/PlainTextEncoder.swift b/Sources/Commands/Utilities/PlainTextEncoder.swift index 00ddc760c9c..cfdcf970b3e 100644 --- a/Sources/Commands/Utilities/PlainTextEncoder.swift +++ b/Sources/Commands/Utilities/PlainTextEncoder.swift @@ -55,12 +55,10 @@ struct PlainTextEncoder { for ch in key.stringValue { if result.isEmpty { result.append(ch.uppercased()) - } - else if ch.isUppercase { + } else if ch.isUppercase { result.append(" ") result.append(ch.lowercased()) - } - else { + } else { result.append(ch) } } @@ -195,12 +193,14 @@ struct PlainTextEncoder { } mutating func nestedContainer(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer { - KeyedEncodingContainer(PlainTextKeyedEncodingContainer( - outputStream: outputStream, - formattingOptions: formattingOptions, - userInfo: userInfo, - codingPath: codingPath - )) + KeyedEncodingContainer( + PlainTextKeyedEncodingContainer( + outputStream: outputStream, + formattingOptions: formattingOptions, + userInfo: userInfo, + codingPath: codingPath + ) + ) } mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer { diff --git a/Sources/Commands/Utilities/PluginDelegate.swift b/Sources/Commands/Utilities/PluginDelegate.swift index e5e82f10126..01f8188c0b7 100644 --- a/Sources/Commands/Utilities/PluginDelegate.swift +++ b/Sources/Commands/Utilities/PluginDelegate.swift @@ -86,7 +86,7 @@ final class PluginDelegate: PluginInvocationDelegate { } var position: Int { - return 0 // should be related to the downstreams somehow + return 0 // should be related to the downstreams somehow } public func write(_ byte: UInt8) { @@ -99,7 +99,7 @@ final class PluginDelegate: PluginInvocationDelegate { for downstream in downstreams { downstream.write(bytes) } - } + } public func flush() { for downstream in downstreams { @@ -197,14 +197,17 @@ final class PluginDelegate: PluginInvocationDelegate { return PluginInvocationBuildResult( succeeded: success, logText: bufferedOutputStream.bytes.cString, - builtArtifacts: builtArtifacts) + builtArtifacts: builtArtifacts + ) } func pluginRequestedTestOperation( subset: PluginInvocationTestSubset, parameters: PluginInvocationTestParameters, - completion: @escaping (Result - ) -> Void) { + completion: @escaping ( + Result + ) -> Void + ) { // Run the test in the background and call the completion handler when done. Task { do { @@ -241,7 +244,7 @@ final class PluginDelegate: PluginInvocationDelegate { toolchain: toolchain, destinationBuildParameters: toolsBuildParameters, sanitizers: swiftCommandState.options.build.sanitizers, - library: .xctest // FIXME: support both libraries + library: .xctest // FIXME: support both libraries ) // Iterate over the tests and run those that match the filter. @@ -268,9 +271,11 @@ final class PluginDelegate: PluginInvocationDelegate { // Check if we should filter out this test. let testSpecifier = testCase.name + "/" + testName if case .filtered(let regexes) = subset { - guard regexes.contains( - where: { testSpecifier.range(of: $0, options: .regularExpression) != nil } - ) else { + guard + regexes.contains( + where: { testSpecifier.range(of: $0, options: .regularExpression) != nil } + ) + else { continue } } @@ -284,11 +289,12 @@ final class PluginDelegate: PluginInvocationDelegate { toolchain: toolchain, testEnv: testEnvironment, observabilityScope: swiftCommandState.observabilityScope, - library: .xctest) // FIXME: support both libraries + library: .xctest + ) // FIXME: support both libraries // Run the test — for now we run the sequentially so we can capture accurate timing results. let startTime = DispatchTime.now() - let result = testRunner.test(outputHandler: { _ in }) // this drops the tests output + let result = testRunner.test(outputHandler: { _ in }) // this drops the tests output let duration = Double(startTime.distance(to: .now()).milliseconds() ?? 0) / 1000.0 numFailedTests += (result != .failure) ? 0 : 1 testResults.append( @@ -304,11 +310,10 @@ final class PluginDelegate: PluginInvocationDelegate { let testTargetName = testCase.name.prefix(while: { $0 != "." }) if let lastTestTargetName = testTargetResults.last?.name, testTargetName == lastTestTargetName { // Same as last one, just extend its list of cases. We know we have a last one at this point. - testTargetResults[testTargetResults.count-1].testCases.append( + testTargetResults[testTargetResults.count - 1].testCases.append( .init(name: testCase.name, tests: testResults) ) - } - else { + } else { // Not the same, so start a new target result. testTargetResults.append( .init( @@ -352,8 +357,7 @@ final class PluginDelegate: PluginInvocationDelegate { // Return the path of the exported code coverage data file. codeCoverageDataFile = jsonCovFile - } - else { + } else { codeCoverageDataFile = nil } @@ -361,7 +365,8 @@ final class PluginDelegate: PluginInvocationDelegate { return PluginInvocationTestResult( succeeded: (numFailedTests == 0), testTargets: testTargetResults, - codeCoverageDataFile: codeCoverageDataFile?.pathString) + codeCoverageDataFile: codeCoverageDataFile?.pathString + ) } func pluginRequestedSymbolGraph( @@ -414,13 +419,14 @@ final class PluginDelegate: PluginInvocationDelegate { // historically how this was setup. Ideally we should be building for both "host" // and "target" if module is configured for them but that would require changing // `PluginInvocationSymbolGraphResult` to carry multiple directories. - let description = if let targetDescription = lookupDescription(for: targetName, destination: .target) { - targetDescription - } else if let hostDescription = lookupDescription(for: targetName, destination: .host) { - hostDescription - } else { - throw InternalError("could not find a target named: \(targetName)") - } + let description = + if let targetDescription = lookupDescription(for: targetName, destination: .target) { + targetDescription + } else if let hostDescription = lookupDescription(for: targetName, destination: .host) { + hostDescription + } else { + throw InternalError("could not find a target named: \(targetName)") + } // Configure the symbol graph extractor. var symbolGraphExtractor = try SymbolGraphExtract( @@ -487,13 +493,15 @@ extension BuildSystem { extension BuildOutput { static func symbolGraph(_ options: PluginInvocationSymbolGraphOptions) -> BuildOutput { - return .symbolGraph(SymbolGraphOptions( + return .symbolGraph( + SymbolGraphOptions( minimumAccessLevel: .accessLevel(options.minimumAccessLevel), includeInheritedDocs: options.includeInheritedDocs, includeSynthesized: options.includeSynthesized, includeSPI: options.includeSPI, emitExtensionBlocks: options.emitExtensionBlocks - )) + ) + ) } } diff --git a/Sources/Commands/Utilities/SymbolGraphExtract.swift b/Sources/Commands/Utilities/SymbolGraphExtract.swift index f18f9aa1b76..490b08bcae7 100644 --- a/Sources/Commands/Utilities/SymbolGraphExtract.swift +++ b/Sources/Commands/Utilities/SymbolGraphExtract.swift @@ -18,9 +18,9 @@ import PackageModel import SPMBuildCore #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import DriverSupport + @_implementationOnly import DriverSupport #else -import DriverSupport + import DriverSupport #endif import class Basics.AsyncProcess @@ -31,7 +31,7 @@ package struct SymbolGraphExtract { let fileSystem: FileSystem let tool: AbsolutePath let observabilityScope: ObservabilityScope - + var skipSynthesizedMembers = false var minimumAccessLevel = AccessLevel.public var skipInheritedDocs = false @@ -50,7 +50,7 @@ package struct SymbolGraphExtract { /// JSON format, optionally "pretty-printed" be more human-readable. case json(pretty: Bool) } - + /// Creates a symbol graph for `module` in `outputDirectory` using the build information from `buildPlan`. /// The `outputDirection` determines how the output from the tool subprocess is handled, and `verbosity` specifies /// how much console output to ask the tool to emit. @@ -80,7 +80,7 @@ package struct SymbolGraphExtract { if includeSPISymbols { commandLine += ["-include-spi-symbols"] } - + let extensionBlockSymbolsFlag = emitExtensionBlockSymbols ? "-emit-extension-block-symbols" : "-omit-extension-block-symbols" if DriverSupport.checkSupportedFrontendFlags( flags: [extensionBlockSymbolsFlag.trimmingCharacters(in: ["-"])], @@ -91,7 +91,7 @@ package struct SymbolGraphExtract { } else { observabilityScope.emit(warning: "dropped \(extensionBlockSymbolsFlag) flag because it is not supported by this compiler version") } - + switch outputFormat { case .json(let pretty): if pretty { diff --git a/Sources/Commands/Utilities/TestingSupport.swift b/Sources/Commands/Utilities/TestingSupport.swift index 81b32961376..d8b5af05b42 100644 --- a/Sources/Commands/Utilities/TestingSupport.swift +++ b/Sources/Commands/Utilities/TestingSupport.swift @@ -39,7 +39,10 @@ enum TestingSupport { func findXCTestHelper(swiftBuildPath: AbsolutePath) -> AbsolutePath? { // XCTestHelper tool is installed in libexec. let maybePath = swiftBuildPath.parentDirectory.parentDirectory.appending( - components: "libexec", "swift", "pm", "swiftpm-xctest-helper" + components: "libexec", + "swift", + "pm", + "swiftpm-xctest-helper" ) if swiftCommandState.fileSystem.isFile(maybePath) { return maybePath @@ -59,7 +62,9 @@ enum TestingSupport { // This will be true during swiftpm development or when using swift.org toolchains. let xcodePath = try AsyncProcess.checkNonZeroExit(args: "/usr/bin/xcode-select", "--print-path").spm_chomp() let installedSwiftBuildPath = try AsyncProcess.checkNonZeroExit( - args: "/usr/bin/xcrun", "--find", "swift-build", + args: "/usr/bin/xcrun", + "--find", + "swift-build", environment: ["DEVELOPER_DIR": xcodePath] ).spm_chomp() if let xctestHelperPath = findXCTestHelper(swiftBuildPath: try AbsolutePath(validating: installedSwiftBuildPath)) { @@ -77,18 +82,21 @@ enum TestingSupport { experimentalTestOutput: Bool, sanitizers: [Sanitizer] ) throws -> [AbsolutePath: [TestSuite]] { - let testSuitesByProduct = try testProducts - .map {( - $0.bundlePath, - try Self.getTestSuites( - fromTestAt: $0.bundlePath, - swiftCommandState: swiftCommandState, - enableCodeCoverage: enableCodeCoverage, - shouldSkipBuilding: shouldSkipBuilding, - experimentalTestOutput: experimentalTestOutput, - sanitizers: sanitizers + let testSuitesByProduct = + try testProducts + .map { + ( + $0.bundlePath, + try Self.getTestSuites( + fromTestAt: $0.bundlePath, + swiftCommandState: swiftCommandState, + enableCodeCoverage: enableCodeCoverage, + shouldSkipBuilding: shouldSkipBuilding, + experimentalTestOutput: experimentalTestOutput, + sanitizers: sanitizers + ) ) - )} + } return try Dictionary(throwingUniqueKeysWithValues: testSuitesByProduct) } @@ -113,45 +121,45 @@ enum TestingSupport { // Run the correct tool. var args = [String]() #if os(macOS) - let data: String = try withTemporaryFile { tempFile in - args = [try Self.xctestHelperPath(swiftCommandState: swiftCommandState).pathString, path.pathString, tempFile.path.pathString] + let data: String = try withTemporaryFile { tempFile in + args = [try Self.xctestHelperPath(swiftCommandState: swiftCommandState).pathString, path.pathString, tempFile.path.pathString] + let env = try Self.constructTestEnvironment( + toolchain: try swiftCommandState.getTargetToolchain(), + destinationBuildParameters: swiftCommandState.buildParametersForTest( + enableCodeCoverage: enableCodeCoverage, + shouldSkipBuilding: shouldSkipBuilding, + experimentalTestOutput: experimentalTestOutput + ).productsBuildParameters, + sanitizers: sanitizers, + library: .xctest + ) + try Self.runProcessWithExistenceCheck( + path: path, + fileSystem: swiftCommandState.fileSystem, + args: args, + env: env + ) + + // Read the temporary file's content. + return try swiftCommandState.fileSystem.readFileContents(AbsolutePath(tempFile.path)) + } + #else let env = try Self.constructTestEnvironment( toolchain: try swiftCommandState.getTargetToolchain(), destinationBuildParameters: swiftCommandState.buildParametersForTest( enableCodeCoverage: enableCodeCoverage, - shouldSkipBuilding: shouldSkipBuilding, - experimentalTestOutput: experimentalTestOutput + shouldSkipBuilding: shouldSkipBuilding ).productsBuildParameters, sanitizers: sanitizers, library: .xctest ) - try Self.runProcessWithExistenceCheck( + args = [path.description, "--dump-tests-json"] + let data = try Self.runProcessWithExistenceCheck( path: path, fileSystem: swiftCommandState.fileSystem, args: args, env: env ) - - // Read the temporary file's content. - return try swiftCommandState.fileSystem.readFileContents(AbsolutePath(tempFile.path)) - } - #else - let env = try Self.constructTestEnvironment( - toolchain: try swiftCommandState.getTargetToolchain(), - destinationBuildParameters: swiftCommandState.buildParametersForTest( - enableCodeCoverage: enableCodeCoverage, - shouldSkipBuilding: shouldSkipBuilding - ).productsBuildParameters, - sanitizers: sanitizers, - library: .xctest - ) - args = [path.description, "--dump-tests-json"] - let data = try Self.runProcessWithExistenceCheck( - path: path, - fileSystem: swiftCommandState.fileSystem, - args: args, - env: env - ) #endif // Parse json and return TestSuites. return try TestSuite.parse(jsonString: data, context: args.joined(separator: " ")) @@ -219,59 +227,59 @@ enum TestingSupport { env["LLVM_PROFILE_FILE"] = codecovProfile.pathString } #if !os(macOS) - #if os(Windows) - if let xctestLocation = toolchain.xctestPath { - env.prependPath(key: .path, value: xctestLocation.pathString) - } - if let swiftTestingLocation = toolchain.swiftTestingPath { - env.prependPath(key: .path, value: swiftTestingLocation.pathString) - } - #endif - return env + #if os(Windows) + if let xctestLocation = toolchain.xctestPath { + env.prependPath(key: .path, value: xctestLocation.pathString) + } + if let swiftTestingLocation = toolchain.swiftTestingPath { + env.prependPath(key: .path, value: swiftTestingLocation.pathString) + } + #endif + return env #else - // Add path to swift-testing override if there is one - if let swiftTestingPath = toolchain.swiftTestingPath { - if swiftTestingPath.extension == "framework" { - env.appendPath(key: "DYLD_FRAMEWORK_PATH", value: swiftTestingPath.pathString) - } else { - env.appendPath(key: "DYLD_LIBRARY_PATH", value: swiftTestingPath.pathString) + // Add path to swift-testing override if there is one + if let swiftTestingPath = toolchain.swiftTestingPath { + if swiftTestingPath.extension == "framework" { + env.appendPath(key: "DYLD_FRAMEWORK_PATH", value: swiftTestingPath.pathString) + } else { + env.appendPath(key: "DYLD_LIBRARY_PATH", value: swiftTestingPath.pathString) + } } - } - // Add the sdk platform path if we have it. - // Since XCTestHelper targets macOS, we need the macOS platform paths here. - if let sdkPlatformPaths = try? SwiftSDK.sdkPlatformPaths(for: .macOS) { - // appending since we prefer the user setting (if set) to the one we inject - for frameworkPath in sdkPlatformPaths.frameworks { - env.appendPath(key: "DYLD_FRAMEWORK_PATH", value: frameworkPath.pathString) + // Add the sdk platform path if we have it. + // Since XCTestHelper targets macOS, we need the macOS platform paths here. + if let sdkPlatformPaths = try? SwiftSDK.sdkPlatformPaths(for: .macOS) { + // appending since we prefer the user setting (if set) to the one we inject + for frameworkPath in sdkPlatformPaths.frameworks { + env.appendPath(key: "DYLD_FRAMEWORK_PATH", value: frameworkPath.pathString) + } + for libraryPath in sdkPlatformPaths.libraries { + env.appendPath(key: "DYLD_LIBRARY_PATH", value: libraryPath.pathString) + } } - for libraryPath in sdkPlatformPaths.libraries { - env.appendPath(key: "DYLD_LIBRARY_PATH", value: libraryPath.pathString) - } - } - // We aren't using XCTest's harness logic to run Swift Testing tests. - if library == .xctest { - env["SWIFT_TESTING_ENABLED"] = "0" - } + // We aren't using XCTest's harness logic to run Swift Testing tests. + if library == .xctest { + env["SWIFT_TESTING_ENABLED"] = "0" + } - // Fast path when no sanitizers are enabled. - if sanitizers.isEmpty { - return env - } + // Fast path when no sanitizers are enabled. + if sanitizers.isEmpty { + return env + } - // Get the runtime libraries. - var runtimes = try sanitizers.map({ sanitizer in - return try toolchain.runtimeLibrary(for: sanitizer).pathString - }) + // Get the runtime libraries. + var runtimes = try sanitizers.map({ sanitizer in + return try toolchain.runtimeLibrary(for: sanitizer).pathString + }) - // Append any existing value to the front. - if let existingValue = env["DYLD_INSERT_LIBRARIES"], !existingValue.isEmpty { - runtimes.insert(existingValue, at: 0) - } + // Append any existing value to the front. + if let existingValue = env["DYLD_INSERT_LIBRARIES"], !existingValue.isEmpty { + runtimes.insert(existingValue, at: 0) + } - env["DYLD_INSERT_LIBRARIES"] = runtimes.joined(separator: ":") - return env + env["DYLD_INSERT_LIBRARIES"] = runtimes.joined(separator: ":") + return env #endif } } diff --git a/Sources/Commands/Utilities/XCTEvents.swift b/Sources/Commands/Utilities/XCTEvents.swift index 0ceedfce77f..23b45500921 100644 --- a/Sources/Commands/Utilities/XCTEvents.swift +++ b/Sources/Commands/Utilities/XCTEvents.swift @@ -197,114 +197,114 @@ extension TestIssue { } } -#if false // This is just here for pre-flighting the code generation done in `SwiftTargetBuildDescription`. -import XCTest - -#if canImport(Darwin) // XCTAttachment is unavailable in swift-corelibs-xctest. -extension TestAttachment { - init(_ attachment: XCTAttachment) { - self.init( - name: attachment.name, - uniformTypeIdentifier: attachment.uniformTypeIdentifier, - payload: attachment.value(forKey: "payload") as? Data - ) - } -} -#endif - -extension TestBundle { - init(_ testBundle: Bundle) { - self.init( - bundleIdentifier: testBundle.bundleIdentifier, - bundlePath: testBundle.bundlePath - ) - } -} - -extension TestCase { - init(_ testCase: XCTestCase) { - self.init(name: testCase.name) +#if false // This is just here for pre-flighting the code generation done in `SwiftTargetBuildDescription`. + import XCTest + + #if canImport(Darwin) // XCTAttachment is unavailable in swift-corelibs-xctest. + extension TestAttachment { + init(_ attachment: XCTAttachment) { + self.init( + name: attachment.name, + uniformTypeIdentifier: attachment.uniformTypeIdentifier, + payload: attachment.value(forKey: "payload") as? Data + ) + } + } + #endif + + extension TestBundle { + init(_ testBundle: Bundle) { + self.init( + bundleIdentifier: testBundle.bundleIdentifier, + bundlePath: testBundle.bundlePath + ) + } } -} -extension TestErrorInfo { - init(_ error: Swift.Error) { - self.init(description: "\(error)", type: "\(Swift.type(of: error))") + extension TestCase { + init(_ testCase: XCTestCase) { + self.init(name: testCase.name) + } } -} -#if canImport(Darwin) // XCTIssue is unavailable in swift-corelibs-xctest. -extension TestIssue { - init(_ issue: XCTIssue) { - self.init( - type: .init(defaultBuildParameters: issue.type), - compactDescription: issue.compactDescription, - detailedDescription: issue.detailedDescription, - associatedError: issue.associatedError.map { .init(defaultBuildParameters: $0) }, - sourceCodeContext: .init(defaultBuildParameters: issue.sourceCodeContext), - attachments: issue.attachments.map { .init(defaultBuildParameters: $0) } - ) + extension TestErrorInfo { + init(_ error: Swift.Error) { + self.init(description: "\(error)", type: "\(Swift.type(of: error))") + } } -} -extension TestIssueType { - init(_ type: XCTIssue.IssueType) { - switch type { - case .assertionFailure: self = .assertionFailure - case .thrownError: self = .thrownError - case .uncaughtException: self = .uncaughtException - case .performanceRegression: self = .performanceRegression - case .system: self = .system - case .unmatchedExpectedFailure: self = .unmatchedExpectedFailure - @unknown default: self = .unknown + #if canImport(Darwin) // XCTIssue is unavailable in swift-corelibs-xctest. + extension TestIssue { + init(_ issue: XCTIssue) { + self.init( + type: .init(defaultBuildParameters: issue.type), + compactDescription: issue.compactDescription, + detailedDescription: issue.detailedDescription, + associatedError: issue.associatedError.map { .init(defaultBuildParameters: $0) }, + sourceCodeContext: .init(defaultBuildParameters: issue.sourceCodeContext), + attachments: issue.attachments.map { .init(defaultBuildParameters: $0) } + ) + } } - } -} -#endif -#if canImport(Darwin) // XCTSourceCodeLocation/XCTSourceCodeContext/XCTSourceCodeFrame/XCTSourceCodeSymbolInfo is unavailable in swift-corelibs-xctest. -extension TestLocation { - init(_ location: XCTSourceCodeLocation) { - self.init( - file: location.fileURL.absoluteString, - line: location.lineNumber - ) - } -} + extension TestIssueType { + init(_ type: XCTIssue.IssueType) { + switch type { + case .assertionFailure: self = .assertionFailure + case .thrownError: self = .thrownError + case .uncaughtException: self = .uncaughtException + case .performanceRegression: self = .performanceRegression + case .system: self = .system + case .unmatchedExpectedFailure: self = .unmatchedExpectedFailure + @unknown default: self = .unknown + } + } + } + #endif + + #if canImport(Darwin) // XCTSourceCodeLocation/XCTSourceCodeContext/XCTSourceCodeFrame/XCTSourceCodeSymbolInfo is unavailable in swift-corelibs-xctest. + extension TestLocation { + init(_ location: XCTSourceCodeLocation) { + self.init( + file: location.fileURL.absoluteString, + line: location.lineNumber + ) + } + } -extension TestSourceCodeContext { - init(_ context: XCTSourceCodeContext) { - self.init( - callStack: context.callStack.map { .init(defaultBuildParameters: $0) }, - location: context.location.map { .init(defaultBuildParameters: $0) } - ) - } -} + extension TestSourceCodeContext { + init(_ context: XCTSourceCodeContext) { + self.init( + callStack: context.callStack.map { .init(defaultBuildParameters: $0) }, + location: context.location.map { .init(defaultBuildParameters: $0) } + ) + } + } -extension TestSourceCodeFrame { - init(_ frame: XCTSourceCodeFrame) { - self.init( - address: frame.address, - symbolInfo: (try? frame.symbolInfo()).map { .init(defaultBuildParameters: $0) }, - symbolicationError: frame.symbolicationError.map { .init(defaultBuildParameters: $0) } - ) - } -} + extension TestSourceCodeFrame { + init(_ frame: XCTSourceCodeFrame) { + self.init( + address: frame.address, + symbolInfo: (try? frame.symbolInfo()).map { .init(defaultBuildParameters: $0) }, + symbolicationError: frame.symbolicationError.map { .init(defaultBuildParameters: $0) } + ) + } + } -extension TestSourceCodeSymbolInfo { - init(_ symbolInfo: XCTSourceCodeSymbolInfo) { - self.init( - imageName: symbolInfo.imageName, - symbolName: symbolInfo.symbolName, - location: symbolInfo.location.map { .init(defaultBuildParameters: $0) } - ) - } -} -#endif + extension TestSourceCodeSymbolInfo { + init(_ symbolInfo: XCTSourceCodeSymbolInfo) { + self.init( + imageName: symbolInfo.imageName, + symbolName: symbolInfo.symbolName, + location: symbolInfo.location.map { .init(defaultBuildParameters: $0) } + ) + } + } + #endif -extension TestSuiteRecord { - init(_ testSuite: XCTestSuite) { - self.init(name: testSuite.name) + extension TestSuiteRecord { + init(_ testSuite: XCTestSuite) { + self.init(name: testSuite.name) + } } -} #endif diff --git a/Sources/CoreCommands/BuildSystemSupport.swift b/Sources/CoreCommands/BuildSystemSupport.swift index b579d11c3fe..d81759b31b4 100644 --- a/Sources/CoreCommands/BuildSystemSupport.swift +++ b/Sources/CoreCommands/BuildSystemSupport.swift @@ -41,11 +41,12 @@ private struct NativeBuildSystemFactory: BuildSystemFactory { ) async throws -> any BuildSystem { _ = try await swiftCommandState.getRootPackageInformation(enableAllTraits) let testEntryPointPath = productsBuildParameters?.testProductStyle.explicitlySpecifiedEntryPointPath - let cacheBuildManifest = if cacheBuildManifest { - try await self.swiftCommandState.canUseCachedBuildManifest() - } else { - false - } + let cacheBuildManifest = + if cacheBuildManifest { + try await self.swiftCommandState.canUseCachedBuildManifest() + } else { + false + } return try BuildOperation( productsBuildParameters: try productsBuildParameters ?? self.swiftCommandState.productsBuildParameters, toolsBuildParameters: try toolsBuildParameters ?? self.swiftCommandState.toolsBuildParameters, @@ -70,7 +71,8 @@ private struct NativeBuildSystemFactory: BuildSystemFactory { logLevel: logLevel ?? self.swiftCommandState.logLevel, fileSystem: self.swiftCommandState.fileSystem, observabilityScope: observabilityScope ?? self.swiftCommandState.observabilityScope, - delegate: delegate) + delegate: delegate + ) } } @@ -150,7 +152,7 @@ extension SwiftCommandState { .init(providers: [ .native: NativeBuildSystemFactory(swiftCommandState: self), .swiftbuild: SwiftBuildSystemFactory(swiftCommandState: self), - .xcode: XcodeBuildSystemFactory(swiftCommandState: self) + .xcode: XcodeBuildSystemFactory(swiftCommandState: self), ]) } } diff --git a/Sources/CoreCommands/Options.swift b/Sources/CoreCommands/Options.swift index 3b7411d8ce9..a0c0184f20a 100644 --- a/Sources/CoreCommands/Options.swift +++ b/Sources/CoreCommands/Options.swift @@ -143,14 +143,14 @@ public struct LocationOptions: ParsableArguments { @Option( name: .customLong("pkg-config-path"), help: - """ - Specify alternative path to search for pkg-config `.pc` files. Use the option multiple times to - specify more than one path. - """, + """ + Specify alternative path to search for pkg-config `.pc` files. Use the option multiple times to + specify more than one path. + """, completion: .directory ) public var pkgConfigDirectories: [AbsolutePath] = [] - + @Option( help: .init("Specify alternate path to search for resources required for SwiftPM to operate. (default: /usr/share/pm)", visibility: .hidden), completion: .directory @@ -198,9 +198,11 @@ public struct CachingOptions: ParsableArguments { } /// Whether to use macro prebuilts or not - @Flag(name: .customLong("experimental-prebuilts"), - inversion: .prefixedEnableDisable, - help: "Whether to use prebuilt swift-syntax libraries for macros.") + @Flag( + name: .customLong("experimental-prebuilts"), + inversion: .prefixedEnableDisable, + help: "Whether to use prebuilt swift-syntax libraries for macros." + ) public var usePrebuilts: Bool = true /// Hidden option to override the prebuilts download location for testing @@ -232,13 +234,15 @@ public struct LoggingOptions: ParsableArguments { @Flag(name: .shortAndLong, help: "Decrease verbosity to only include error output.") public var quiet: Bool = false - @Flag(name: .customLong("color-diagnostics"), - inversion: .prefixedNo, - help: + @Flag( + name: .customLong("color-diagnostics"), + inversion: .prefixedNo, + help: """ Enables or disables color diagnostics when printing to a TTY. By default, color diagnostics are enabled when connected to a TTY and disabled otherwise. - """) + """ + ) public var colorDiagnostics: Bool = ProcessInfo.processInfo.environment["NO_COLOR"] == nil } @@ -275,19 +279,19 @@ public struct SecurityOptions: ParsableArguments { /// when downloading binary artifacts. This has no effects on registry /// communications. #if canImport(Security) - @Flag( - inversion: .prefixedEnableDisable, - exclusivity: .exclusive, - help: "Search credentials in macOS keychain." - ) - public var keychain: Bool = true + @Flag( + inversion: .prefixedEnableDisable, + exclusivity: .exclusive, + help: "Search credentials in macOS keychain." + ) + public var keychain: Bool = true #else - @Flag( - inversion: .prefixedEnableDisable, - exclusivity: .exclusive, - help: .hidden - ) - public var keychain: Bool = false + @Flag( + inversion: .prefixedEnableDisable, + exclusivity: .exclusive, + help: .hidden + ) + public var keychain: Bool = false #endif @Option(name: .customLong("resolver-fingerprint-checking")) @@ -435,9 +439,7 @@ public struct BuildOptions: ParsableArguments { public var _deprecated_manifestFlags: [String] = [] var manifestFlags: [String] { - self._deprecated_manifestFlags.isEmpty ? - self._buildToolsSwiftCFlags : - self._deprecated_manifestFlags + self._deprecated_manifestFlags.isEmpty ? self._buildToolsSwiftCFlags : self._deprecated_manifestFlags } var pluginSwiftCFlags: [String] { @@ -592,7 +594,7 @@ public struct BuildOptions: ParsableArguments { public var enableTaskBacktraces: Bool = false // Build dynamic library targets as frameworks (only available for Darwin targets and only when using the 'swiftbuild' build-system (currently used for tests). - @Flag(name: .customLong("experimental-build-dylibs-as-frameworks"), help: .hidden ) + @Flag(name: .customLong("experimental-build-dylibs-as-frameworks"), help: .hidden) public var shouldBuildDylibsAsFrameworks: Bool = false // @Flag works best when there is a default value present @@ -653,26 +655,32 @@ public struct TestLibraryOptions: ParsableArguments { /// /// Callers will generally want to use ``enableXCTestSupport`` since it will /// have the correct default value if the user didn't specify one. - @Flag(name: .customLong("xctest"), - inversion: .prefixedEnableDisable, - help: "Enable support for XCTest.") + @Flag( + name: .customLong("xctest"), + inversion: .prefixedEnableDisable, + help: "Enable support for XCTest." + ) public var explicitlyEnableXCTestSupport: Bool? /// Whether to enable support for Swift Testing (as explicitly specified by the user.) /// /// Callers will generally want to use ``enableSwiftTestingLibrarySupport`` since it will /// have the correct default value if the user didn't specify one. - @Flag(name: .customLong("swift-testing"), - inversion: .prefixedEnableDisable, - help: "Enable support for Swift Testing.") + @Flag( + name: .customLong("swift-testing"), + inversion: .prefixedEnableDisable, + help: "Enable support for Swift Testing." + ) public var explicitlyEnableSwiftTestingLibrarySupport: Bool? /// Legacy experimental equivalent of ``explicitlyEnableSwiftTestingLibrarySupport``. /// /// This option will be removed in a future update. - @Flag(name: .customLong("experimental-swift-testing"), - inversion: .prefixedEnableDisable, - help: .private) + @Flag( + name: .customLong("experimental-swift-testing"), + inversion: .prefixedEnableDisable, + help: .private + ) public var explicitlyEnableExperimentalSwiftTestingLibrarySupport: Bool? /// The common implementation for `isEnabled()` and `isExplicitlyEnabled()`. @@ -687,7 +695,8 @@ public struct TestLibraryOptions: ParsableArguments { return explicitlyEnableXCTestSupport } if let toolchain = try? swiftCommandState.getHostToolchain(), - toolchain.swiftSDK.xctestSupport == .supported { + toolchain.swiftSDK.xctestSupport == .supported + { return `default` } return false diff --git a/Sources/CoreCommands/SwiftCommandObservabilityHandler.swift b/Sources/CoreCommands/SwiftCommandObservabilityHandler.swift index aa49fffcc94..5637231115e 100644 --- a/Sources/CoreCommands/SwiftCommandObservabilityHandler.swift +++ b/Sources/CoreCommands/SwiftCommandObservabilityHandler.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import Dispatch import PackageModel @@ -39,8 +38,7 @@ public struct SwiftCommandObservabilityHandler: ObservabilityHandlerProvider { /// emitted below this level will be ignored. public init(outputStream: OutputByteStream, logLevel: Basics.Diagnostic.Severity, colorDiagnostics: Bool = true) { - let threadSafeOutputByteStream = outputStream as? ThreadSafeOutputByteStream ?? - ThreadSafeOutputByteStream(outputStream) + let threadSafeOutputByteStream = outputStream as? ThreadSafeOutputByteStream ?? ThreadSafeOutputByteStream(outputStream) self.outputHandler = OutputHandler( logLevel: logLevel, outputStream: threadSafeOutputByteStream, diff --git a/Sources/CoreCommands/SwiftCommandState.swift b/Sources/CoreCommands/SwiftCommandState.swift index b4a6158274b..93f34a8cceb 100644 --- a/Sources/CoreCommands/SwiftCommandState.swift +++ b/Sources/CoreCommands/SwiftCommandState.swift @@ -19,8 +19,7 @@ import class Foundation.ProcessInfo import PackageFingerprint import PackageGraph import PackageLoading -@_spi(SwiftPMInternal) -import PackageModel +@_spi(SwiftPMInternal) import PackageModel import PackageRegistry import PackageSigning import SourceControl @@ -28,24 +27,21 @@ import SPMBuildCore import Workspace #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly -@_spi(SwiftPMInternal) -import DriverSupport + @_implementationOnly @_spi(SwiftPMInternal) import DriverSupport #else -@_spi(SwiftPMInternal) -import DriverSupport + @_spi(SwiftPMInternal) import DriverSupport #endif #if canImport(WinSDK) -import WinSDK + import WinSDK #elseif canImport(Darwin) -import Darwin + import Darwin #elseif canImport(Glibc) -import Glibc + import Glibc #elseif canImport(Musl) -import Musl + import Musl #elseif canImport(Bionic) -import Bionic + import Bionic #endif import class Basics.AsyncProcess @@ -198,8 +194,8 @@ extension AsyncSwiftCommand { public final class SwiftCommandState { #if os(Windows) - // unfortunately this is needed for C callback handlers used by Windows shutdown handler - static var cancellator: Cancellator? + // unfortunately this is needed for C callback handlers used by Windows shutdown handler + static var cancellator: Cancellator? #endif /// The original working directory. @@ -244,7 +240,7 @@ public final class SwiftCommandState { /// Path to the shared configuration directory public let sharedConfigurationDirectory: AbsolutePath - + /// Path to the package manager's own resources directory. public let packageManagerResourcesDirectory: AbsolutePath? @@ -389,9 +385,7 @@ public final class SwiftCommandState { self.packageRoot = packageRoot self.scratchDirectory = - try BuildSystemUtilities.getEnvBuildPath(workingDir: cwd) ?? - options.locations.scratchDirectory ?? - (packageRoot ?? cwd).appending(".build") + try BuildSystemUtilities.getEnvBuildPath(workingDir: cwd) ?? options.locations.scratchDirectory ?? (packageRoot ?? cwd).appending(".build") // make sure common directories are created self.sharedSecurityDirectory = try getSharedSecurityDirectory(options: options, fileSystem: fileSystem) @@ -405,7 +399,7 @@ public final class SwiftCommandState { warning: "`--experimental-swift-sdks-path` is deprecated and will be removed in a future version of SwiftPM. Use `--swift-sdks-path` instead." ) } - + if let packageManagerResourcesDirectory = options.locations.packageManagerResourcesDirectory { self.packageManagerResourcesDirectory = packageManagerResourcesDirectory } else if let cwd = localFileSystem.currentWorkingDirectory { @@ -415,7 +409,7 @@ public final class SwiftCommandState { self.packageManagerResourcesDirectory = try? AbsolutePath(validating: CommandLine.arguments[0]) .parentDirectory.parentDirectory.appending(components: ["share", "pm"]) } - + self.sharedSwiftSDKsDirectory = try fileSystem.getSharedSwiftSDKsDirectory( explicitDirectory: options.locations.swiftSDKsDirectory ?? options.locations.deprecatedSwiftSDKsDirectory ) @@ -438,12 +432,12 @@ public final class SwiftCommandState { // --enable-test-discovery should never be called on darwin based platforms #if canImport(Darwin) - if options.build.enableTestDiscovery { - observabilityScope - .emit( - warning: "'--enable-test-discovery' option is deprecated; tests are automatically discovered on all platforms" - ) - } + if options.build.enableTestDiscovery { + observabilityScope + .emit( + warning: "'--enable-test-discovery' option is deprecated; tests are automatically discovered on all platforms" + ) + } #endif if options.caching.shouldDisableManifestCaching { @@ -669,7 +663,8 @@ public final class SwiftCommandState { let legacyPath = multiRootPackageDataFile.appending(components: "xcshareddata", "swiftpm", "config") let newPath = Workspace.DefaultLocations .mirrorsConfigurationFile( - at: multiRootPackageDataFile + at: + multiRootPackageDataFile .appending(components: "xcshareddata", "swiftpm", "configuration") ) return try Workspace.migrateMirrorsConfiguration( @@ -700,7 +695,7 @@ public final class SwiftCommandState { } #if canImport(Security) - authorization.keychain = self.options.security.keychain ? .enabled : .disabled + authorization.keychain = self.options.security.keychain ? .enabled : .disabled #endif return try authorization.makeAuthorizationProvider( @@ -719,7 +714,7 @@ public final class SwiftCommandState { // Don't use OS credential store if user wants netrc #if canImport(Security) - authorization.keychain = self.options.security.forceNetrc ? .disabled : .enabled + authorization.keychain = self.options.security.forceNetrc ? .disabled : .enabled #endif return try authorization.makeRegistryAuthorizationProvider( @@ -834,8 +829,7 @@ public final class SwiftCommandState { let buildParameters = try self.productsBuildParameters let haveBuildManifestAndDescription = - self.fileSystem.exists(buildParameters.llbuildManifest) && - self.fileSystem.exists(buildParameters.buildDescriptionPath) + self.fileSystem.exists(buildParameters.llbuildManifest) && self.fileSystem.exists(buildParameters.buildDescriptionPath) if !haveBuildManifestAndDescription { return false @@ -900,9 +894,9 @@ public final class SwiftCommandState { } static let entitlementsMacOSWarning = """ - `--disable-get-task-allow-entitlement` and `--disable-get-task-allow-entitlement` only have an effect \ - when building on macOS. - """ + `--disable-get-task-allow-entitlement` and `--disable-get-task-allow-entitlement` only have an effect \ + when building on macOS. + """ private func _buildParams( toolchain: UserToolchain, @@ -946,9 +940,8 @@ public final class SwiftCommandState { debugInfoFormat: self.options.build.debugInfoFormat.buildParameter, triple: triple, shouldEnableDebuggingEntitlement: - self.options.build - .getTaskAllowEntitlement ?? - (self.options.build.configuration ?? self.preferredBuildConfiguration == .debug), + self.options.build + .getTaskAllowEntitlement ?? (self.options.build.configuration ?? self.preferredBuildConfiguration == .debug), omitFramePointers: self.options.build.omitFramePointers ), driverParameters: .init( @@ -1059,7 +1052,8 @@ public final class SwiftCommandState { swiftSDK: swiftSDK, environment: self.environment, customTargetInfo: targetInfo, - fileSystem: self.fileSystem) + fileSystem: self.fileSystem + ) }) }() @@ -1080,20 +1074,21 @@ public final class SwiftCommandState { }) private lazy var _manifestLoader: Result = Result(catching: { - let cachePath: AbsolutePath? = switch ( - self.options.caching.shouldDisableManifestCaching, - self.options.caching.manifestCachingMode - ) { - case (true, _): - // backwards compatibility - .none - case (false, .none): - .none - case (false, .local): - self.scratchDirectory - case (false, .shared): - Workspace.DefaultLocations.manifestsDirectory(at: self.sharedCacheDirectory) - } + let cachePath: AbsolutePath? = + switch ( + self.options.caching.shouldDisableManifestCaching, + self.options.caching.manifestCachingMode + ) { + case (true, _): + // backwards compatibility + .none + case (false, .none): + .none + case (false, .local): + self.scratchDirectory + case (false, .shared): + Workspace.DefaultLocations.manifestsDirectory(at: self.sharedCacheDirectory) + } var extraManifestFlags = self.options.build.manifestFlags if self.logLevel <= .info { @@ -1163,7 +1158,7 @@ public final class SwiftCommandState { if errno == EWOULDBLOCK { let lockingPID = try? String(contentsOfFile: lockFile, encoding: .utf8) let pidInfo = lockingPID.map { "(PID: \($0)) " } ?? "" - + if self.options.locations.ignoreLock { self.outputStream .write( @@ -1390,4 +1385,3 @@ extension Basics.Diagnostic { .error(arguments.map { "'\($0)'" }.spm_localizedJoin(type: .conjunction) + " are mutually exclusive") } } - diff --git a/Sources/DriverSupport/DriverSupportUtils.swift b/Sources/DriverSupport/DriverSupportUtils.swift index 1497ec1b94a..ede5ac589bc 100644 --- a/Sources/DriverSupport/DriverSupportUtils.swift +++ b/Sources/DriverSupport/DriverSupportUtils.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import Foundation import PackageModel import SwiftDriver diff --git a/Sources/DriverSupport/SPMSwiftDriverExecutor.swift b/Sources/DriverSupport/SPMSwiftDriverExecutor.swift index e20f8b207da..3653d8510f2 100644 --- a/Sources/DriverSupport/SPMSwiftDriverExecutor.swift +++ b/Sources/DriverSupport/SPMSwiftDriverExecutor.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import SwiftDriver @@ -19,10 +18,10 @@ import class TSCBasic.Process import struct TSCBasic.ProcessResult public final class SPMSwiftDriverExecutor: DriverExecutor { - + private enum Error: Swift.Error, CustomStringConvertible { case inPlaceExecutionUnsupported - + var description: String { switch self { case .inPlaceExecutionUnsupported: @@ -30,62 +29,74 @@ public final class SPMSwiftDriverExecutor: DriverExecutor { } } } - + public let resolver: ArgsResolver let fileSystem: FileSystem let env: Environment - public init(resolver: ArgsResolver, - fileSystem: FileSystem, - env: Environment) { + public init( + resolver: ArgsResolver, + fileSystem: FileSystem, + env: Environment + ) { self.resolver = resolver self.fileSystem = fileSystem self.env = env } - - public func execute(job: Job, - forceResponseFiles: Bool, - recordedInputModificationDates: [TypedVirtualPath : TimePoint]) throws -> ProcessResult { - let arguments: [String] = try resolver.resolveArgumentList(for: job, - useResponseFiles: forceResponseFiles ? .forced : .heuristic) - - try job.verifyInputsNotModified(since: recordedInputModificationDates, - fileSystem: fileSystem) - + + public func execute( + job: Job, + forceResponseFiles: Bool, + recordedInputModificationDates: [TypedVirtualPath: TimePoint] + ) throws -> ProcessResult { + let arguments: [String] = try resolver.resolveArgumentList( + for: job, + useResponseFiles: forceResponseFiles ? .forced : .heuristic + ) + + try job.verifyInputsNotModified( + since: recordedInputModificationDates, + fileSystem: fileSystem + ) + if job.requiresInPlaceExecution { throw Error.inPlaceExecutionUnsupported } - - + var childEnv = [String: String](env) childEnv.merge(job.extraEnvironment, uniquingKeysWith: { (_, new) in new }) let process = try Process.launchProcess(arguments: arguments, env: childEnv) return try process.waitUntilExit() } - - public func execute(workload: DriverExecutorWorkload, - delegate: JobExecutionDelegate, - numParallelJobs: Int, forceResponseFiles: Bool, - recordedInputModificationDates: [TypedVirtualPath : TimePoint]) throws { + + public func execute( + workload: DriverExecutorWorkload, + delegate: JobExecutionDelegate, + numParallelJobs: Int, + forceResponseFiles: Bool, + recordedInputModificationDates: [TypedVirtualPath: TimePoint] + ) throws { throw InternalError("Multi-job build plans should be lifted into the SPM build graph.") } - - public func checkNonZeroExit(args: String..., environment: [String : String]) throws -> String { + + public func checkNonZeroExit(args: String..., environment: [String: String]) throws -> String { try AsyncProcess.checkNonZeroExit(arguments: args, environment: .init(environment)) } - + public func description(of job: Job, forceResponseFiles: Bool) throws -> String { // FIXME: This is duplicated from SwiftDriver, maybe it shouldn't be a protocol requirement. - let (args, usedResponseFile) = try resolver.resolveArgumentList(for: job, - useResponseFiles: forceResponseFiles ? .forced : .heuristic) + let (args, usedResponseFile) = try resolver.resolveArgumentList( + for: job, + useResponseFiles: forceResponseFiles ? .forced : .heuristic + ) var result = args.joined(separator: " ") - + if usedResponseFile { // Print the response file arguments as a comment. result += " # \(job.commandLine.joinedUnresolvedArguments)" } - + if !job.extraEnvironment.isEmpty { result += " #" for (envVar, val) in job.extraEnvironment { diff --git a/Sources/LLBuildManifest/LLBuildManifest.swift b/Sources/LLBuildManifest/LLBuildManifest.swift index 520db084769..6b5c1a2d927 100644 --- a/Sources/LLBuildManifest/LLBuildManifest.swift +++ b/Sources/LLBuildManifest/LLBuildManifest.swift @@ -74,7 +74,8 @@ public enum WriteAuxiliary { } } - var content = objects + var content = + objects .map { $0.spm_shellEscaped() } .joined(separator: "\n") @@ -105,7 +106,8 @@ public enum WriteAuxiliary { guard sources.count > 0 else { return "" } - var contents = sources + var contents = + sources .map { $0.spm_shellEscaped() } .joined(separator: "\n") contents.append("\n") @@ -364,11 +366,11 @@ public struct LLBuildManifest { arguments: [String] ) { let tool = SwiftFrontendTool( - moduleName: moduleName, - description: description, - inputs: inputs, - outputs: outputs, - arguments: arguments + moduleName: moduleName, + description: description, + inputs: inputs, + outputs: outputs, + arguments: arguments ) addCommand(name: name, tool: tool) } diff --git a/Sources/LLBuildManifest/LLBuildManifestWriter.swift b/Sources/LLBuildManifest/LLBuildManifestWriter.swift index d902aca8ca0..9842c09ec4f 100644 --- a/Sources/LLBuildManifest/LLBuildManifestWriter.swift +++ b/Sources/LLBuildManifest/LLBuildManifestWriter.swift @@ -19,12 +19,12 @@ public struct LLBuildManifestWriter { // FIXME: since JSON is a superset of YAML and we don't need to parse these manifests, // we should just use `JSONEncoder` instead. private var buffer = """ - client: - name: basic - file-system: device-agnostic - tools: {} + client: + name: basic + file-system: device-agnostic + tools: {} - """ + """ private init(manifest: LLBuildManifest) { self.manifest = manifest @@ -79,27 +79,27 @@ public struct LLBuildManifestWriter { private mutating func render(directoryStructure node: Node) { self.buffer += """ - \(node.asJSON): - is-directory-structure: true - content-exclusion-patterns: \(namesToExclude.asJSON) + \(node.asJSON): + is-directory-structure: true + content-exclusion-patterns: \(namesToExclude.asJSON) - """ + """ } private mutating func render(isCommandTimestamp node: Node) { self.buffer += """ - \(node.asJSON): - is-command-timestamp: true + \(node.asJSON): + is-command-timestamp: true - """ + """ } private mutating func render(isMutated node: Node) { self.buffer += """ - \(node.asJSON): - is-mutated: true + \(node.asJSON): + is-mutated: true - """ + """ } private mutating func render(commands: [LLBuildManifest.CmdName: Command]) { @@ -237,62 +237,65 @@ extension String { private var jsonEscaped: String { // See RFC7159 for reference: https://tools.ietf.org/html/rfc7159 - String(decoding: self.utf8.flatMap { character -> [UInt8] in - // Handle string escapes; we use constants here to directly match the RFC. - switch character { - // Literal characters. - case 0x20 ... 0x21, 0x23 ... 0x5B, 0x5D ... 0xFF: - return [character] - - // Single-character escaped characters. - case 0x22: // '"' - return [ - 0x5C, // '\' - 0x22, // '"' - ] - case 0x5C: // '\\' - return [ - 0x5C, // '\' - 0x5C, // '\' - ] - case 0x08: // '\b' - return [ - 0x5C, // '\' - 0x62, // 'b' - ] - case 0x0C: // '\f' - return [ - 0x5C, // '\' - 0x66, // 'b' - ] - case 0x0A: // '\n' - return [ - 0x5C, // '\' - 0x6E, // 'n' - ] - case 0x0D: // '\r' - return [ - 0x5C, // '\' - 0x72, // 'r' - ] - case 0x09: // '\t' - return [ - 0x5C, // '\' - 0x74, // 't' - ] - - // Multi-character escaped characters. - default: - return [ - 0x5C, // '\' - 0x75, // 'u' - hexdigit(0), - hexdigit(0), - hexdigit(character >> 4), - hexdigit(character & 0xF), - ] - } - }, as: UTF8.self) + String( + decoding: self.utf8.flatMap { character -> [UInt8] in + // Handle string escapes; we use constants here to directly match the RFC. + switch character { + // Literal characters. + case 0x20...0x21, 0x23...0x5B, 0x5D...0xFF: + return [character] + + // Single-character escaped characters. + case 0x22: // '"' + return [ + 0x5C, // '\' + 0x22, // '"' + ] + case 0x5C: // '\\' + return [ + 0x5C, // '\' + 0x5C, // '\' + ] + case 0x08: // '\b' + return [ + 0x5C, // '\' + 0x62, // 'b' + ] + case 0x0C: // '\f' + return [ + 0x5C, // '\' + 0x66, // 'b' + ] + case 0x0A: // '\n' + return [ + 0x5C, // '\' + 0x6E, // 'n' + ] + case 0x0D: // '\r' + return [ + 0x5C, // '\' + 0x72, // 'r' + ] + case 0x09: // '\t' + return [ + 0x5C, // '\' + 0x74, // 't' + ] + + // Multi-character escaped characters. + default: + return [ + 0x5C, // '\' + 0x75, // 'u' + hexdigit(0), + hexdigit(0), + hexdigit(character >> 4), + hexdigit(character & 0xF), + ] + } + }, + as: UTF8.self + ) } } diff --git a/Sources/LLBuildManifest/Node.swift b/Sources/LLBuildManifest/Node.swift index 9dd898b6682..dd7f270be5a 100644 --- a/Sources/LLBuildManifest/Node.swift +++ b/Sources/LLBuildManifest/Node.swift @@ -38,7 +38,7 @@ public struct Node: Hashable, Codable { self.kind = kind self.attributes = attributes } - + /// Extracts `name` property if this node was constructed as `Node//virtual`. public var extractedVirtualNodeName: String { precondition(kind == .virtual) diff --git a/Sources/PackageCollections/API.swift b/Sources/PackageCollections/API.swift index 48351222c03..4b8198b1fc6 100644 --- a/Sources/PackageCollections/API.swift +++ b/Sources/PackageCollections/API.swift @@ -160,7 +160,6 @@ public protocol PackageCollectionsProtocol { ) async throws -> PackageCollectionsModel.TargetSearchResult } - public enum PackageCollectionError: Equatable, Error { /// Package collection is not signed and there is no record of user's trust selection case trustConfirmationRequired @@ -184,7 +183,7 @@ public enum PackageCollectionError: Equatable, Error { public protocol PackageIndexProtocol { /// Returns true if the package index is configured. var isEnabled: Bool { get } - + /// Returns metadata for the package identified by the given `PackageIdentity`. /// /// A failure is returned if the package is not found. @@ -221,7 +220,7 @@ public enum PackageIndexError: Equatable, Error { case featureDisabled /// No package index configured case notConfigured - + case invalidURL(URL) case invalidResponse(URL, String) } diff --git a/Sources/PackageCollections/Model/Collection.swift b/Sources/PackageCollections/Model/Collection.swift index 7d335ce6924..7a1339660a8 100644 --- a/Sources/PackageCollections/Model/Collection.swift +++ b/Sources/PackageCollections/Model/Collection.swift @@ -237,10 +237,12 @@ extension PackageCollectionsModel { public let organization: String? /// Creates a `Name` - public init(userID: String?, - commonName: String?, - organizationalUnit: String?, - organization: String?) { + public init( + userID: String?, + commonName: String?, + organizationalUnit: String?, + organization: String? + ) { self.userID = userID self.commonName = commonName self.organizationalUnit = organizationalUnit diff --git a/Sources/PackageCollections/Model/PackageList.swift b/Sources/PackageCollections/Model/PackageList.swift index e473785930d..89a9c5cc6a0 100644 --- a/Sources/PackageCollections/Model/PackageList.swift +++ b/Sources/PackageCollections/Model/PackageList.swift @@ -18,10 +18,10 @@ extension PackageCollectionsModel { /// Offset of the first item in the result public let offset: Int - + /// The requested page size public let limit: Int - + /// Total number of packages public let total: Int } diff --git a/Sources/PackageCollections/Model/PackageTypes.swift b/Sources/PackageCollections/Model/PackageTypes.swift index e915ad58f58..7f3490fb589 100644 --- a/Sources/PackageCollections/Model/PackageTypes.swift +++ b/Sources/PackageCollections/Model/PackageTypes.swift @@ -128,7 +128,7 @@ extension PackageCollectionsModel.Package { /// Package version description public let summary: String? - + /// Manifests by tools version public let manifests: [ToolsVersion: Manifest] @@ -140,10 +140,10 @@ extension PackageCollectionsModel.Package { /// The package version's license public let license: PackageCollectionsModel.License? - + /// The package version's author public let author: PackageCollectionsModel.Package.Author? - + /// The package version's signer public let signer: PackageCollectionsModel.Signer? @@ -231,13 +231,13 @@ extension PackageCollectionsModel { public struct Signer: Equatable, Codable { /// The signer type. public let type: SignerType - + /// The common name of the signing certificate's subject. public let commonName: String - + /// The organizational unit name of the signing certificate's subject. public let organizationalUnitName: String - + /// The organization name of the signing certificate's subject. public let organizationName: String @@ -253,9 +253,9 @@ extension PackageCollectionsModel { self.organizationName = organizationName } } - + public enum SignerType: String, Codable { - case adp // Apple Developer Program + case adp // Apple Developer Program } } diff --git a/Sources/PackageCollections/Model/Search.swift b/Sources/PackageCollections/Model/Search.swift index c593103241c..5405fd5546d 100644 --- a/Sources/PackageCollections/Model/Search.swift +++ b/Sources/PackageCollections/Model/Search.swift @@ -26,10 +26,10 @@ extension PackageCollectionsModel { /// Package collections that contain the package public internal(set) var collections: [PackageCollectionsModel.CollectionIdentifier] - + /// Package indexes that contain the package public internal(set) var indexes: [URL] - + init( package: PackageCollectionsModel.Package, collections: [PackageCollectionsModel.CollectionIdentifier] = [], diff --git a/Sources/PackageCollections/PackageCollections+CertificatePolicy.swift b/Sources/PackageCollections/PackageCollections+CertificatePolicy.swift index e92fda539d5..6c4b3049f54 100644 --- a/Sources/PackageCollections/PackageCollections+CertificatePolicy.swift +++ b/Sources/PackageCollections/PackageCollections+CertificatePolicy.swift @@ -32,8 +32,8 @@ internal struct PackageCollectionSourceCertificatePolicy { // AppleRootCA-G3.cer "MIICQzCCAcmgAwIBAgIILcX8iNLFS5UwCgYIKoZIzj0EAwMwZzEbMBkGA1UEAwwSQXBwbGUgUm9vdCBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwHhcNMTQwNDMwMTgxOTA2WhcNMzkwNDMwMTgxOTA2WjBnMRswGQYDVQQDDBJBcHBsZSBSb290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzB2MBAGByqGSM49AgEGBSuBBAAiA2IABJjpLz1AcqTtkyJygRMc3RCV8cWjTnHcFBbZDuWmBSp3ZHtfTjjTuxxEtX/1H7YyYl3J6YRbTzBPEVoA/VhYDKX1DyxNB0cTddqXl5dvMVztK517IDvYuVTZXpmkOlEKMaNCMEAwHQYDVR0OBBYEFLuw3qFYM4iapIqZ3r6966/ayySrMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMQCD6cHEFl4aXTQY2e3v9GwOAEZLuN+yRhHFD/3meoyhpmvOwgPUnPWTxnS4at+qIxUCMG1mihDK1A3UT82NQz60imOlM27jbdoXt2QfyFMm+YhidDkLF1vLUagM6BgD56KyKA==", ] - ), - ], + ) + ] ] private let sourceCertPolicies: [String: [CertificatePolicyConfig]] diff --git a/Sources/PackageCollections/PackageCollections+Configuration.swift b/Sources/PackageCollections/PackageCollections+Configuration.swift index 17deee1f5d1..4fbbfb8c540 100644 --- a/Sources/PackageCollections/PackageCollections+Configuration.swift +++ b/Sources/PackageCollections/PackageCollections+Configuration.swift @@ -18,10 +18,10 @@ extension PackageCollections { // TODO: add configuration including: // JSONPackageCollectionProvider: maximumSizeInBytes // JSONPackageCollectionValidator: maximumPackageCount, maximumMajorVersionCount, maximumMinorVersionCount - + /// Path of the parent directory for collections-related configuration files public var configurationDirectory: AbsolutePath? - + /// Path of the parent directory for collections-related cache(s) public var cacheDirectory: AbsolutePath? diff --git a/Sources/PackageCollections/PackageCollections+Validation.swift b/Sources/PackageCollections/PackageCollections+Validation.swift index c0e7bbd5c2e..303b90c962f 100644 --- a/Sources/PackageCollections/PackageCollections+Validation.swift +++ b/Sources/PackageCollections/PackageCollections+Validation.swift @@ -172,9 +172,11 @@ extension PackageCollectionModel.V1 { public var maximumMajorVersionCount: Int public var maximumMinorVersionCount: Int - public init(maximumPackageCount: Int? = nil, - maximumMajorVersionCount: Int? = nil, - maximumMinorVersionCount: Int? = nil) { + public init( + maximumPackageCount: Int? = nil, + maximumMajorVersionCount: Int? = nil, + maximumMinorVersionCount: Int? = nil + ) { // TODO: where should we read defaults from? self.maximumPackageCount = maximumPackageCount ?? 50 self.maximumMajorVersionCount = maximumMajorVersionCount ?? 2 @@ -234,7 +236,7 @@ extension Array where Element == ValidationMessage { public enum ValidationError: Error, Equatable, CustomStringConvertible { case property(name: String, message: String) case other(message: String) - + public var message: String { switch self { case .property(_, let message): diff --git a/Sources/PackageCollections/PackageCollections.swift b/Sources/PackageCollections/PackageCollections.swift index 17db7491bf1..d0a28bf30d1 100644 --- a/Sources/PackageCollections/PackageCollections.swift +++ b/Sources/PackageCollections/PackageCollections.swift @@ -21,9 +21,9 @@ import protocol TSCBasic.Closable public struct PackageCollections: PackageCollectionsProtocol, Closable { // Check JSONPackageCollectionProvider.isSignatureCheckSupported before updating or removing this #if os(macOS) || os(Linux) || os(Windows) || os(Android) - static let isSupportedPlatform = true + static let isSupportedPlatform = true #else - static let isSupportedPlatform = false + static let isSupportedPlatform = false #endif let configuration: Configuration @@ -50,7 +50,7 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { observabilityScope: observabilityScope ) } - + init( configuration: Configuration = .init(), customMetadataProvider: PackageMetadataProvider?, @@ -75,13 +75,15 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { ) ] - let metadataProvider = customMetadataProvider ?? GitHubPackageMetadataProvider( - configuration: .init( - authTokens: configuration.authTokens, - cacheDir: configuration.cacheDirectory?.appending(components: "package-metadata") - ), - observabilityScope: observabilityScope - ) + let metadataProvider = + customMetadataProvider + ?? GitHubPackageMetadataProvider( + configuration: .init( + authTokens: configuration.authTokens, + cacheDir: configuration.cacheDirectory?.appending(components: "package-metadata") + ), + observabilityScope: observabilityScope + ) self.configuration = configuration self.fileSystem = fileSystem @@ -92,12 +94,13 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { } // internal initializer for testing - init(configuration: Configuration = .init(), - fileSystem: FileSystem, - observabilityScope: ObservabilityScope, - storage: Storage, - collectionProviders: [Model.CollectionSourceType: PackageCollectionProvider], - metadataProvider: PackageMetadataProvider + init( + configuration: Configuration = .init(), + fileSystem: FileSystem, + observabilityScope: ObservabilityScope, + storage: Storage, + collectionProviders: [Model.CollectionSourceType: PackageCollectionProvider], + metadataProvider: PackageMetadataProvider ) { self.configuration = configuration self.fileSystem = fileSystem @@ -111,12 +114,12 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { if self.storageContainer.owned { try self.storageContainer.storage.close() } - + if let metadataProvider = self.metadataProvider as? Closable { try metadataProvider.close() } } - + public func close() throws { try self.shutdown() } @@ -288,7 +291,7 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { public func findPackages( _ query: String, collections: Set? = nil - ) async throws -> PackageCollectionsModel.PackageSearchResult{ + ) async throws -> PackageCollectionsModel.PackageSearchResult { guard Self.isSupportedPlatform else { throw PackageCollectionError.unsupportedPlatform } @@ -323,7 +326,7 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { return PackageCollectionsModel.PackageSearchResult( items: packageCollections.sorted { $0.value.package.displayName < $1.value.package.displayName } .map { entry in - .init(package: entry.value.package, collections: Array(entry.value.collections)) + .init(package: entry.value.package, collections: Array(entry.value.collections)) } ) } @@ -427,7 +430,6 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { return try await self.storage.collections.put(collection: collection) } - // No user preference recorded, so we need to prompt if we can. guard let trustConfirmationProvider else { // Try to remove the untrusted collection (if previously saved) from storage before calling back @@ -453,9 +455,10 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { return try await self.storage.collections.put(collection: collection) } - func findPackage(identity: PackageIdentity, - location: String? = nil, - collections: Set? = nil + func findPackage( + identity: PackageIdentity, + location: String? = nil, + collections: Set? = nil ) async throws -> PackageCollectionsModel.PackageSearchResult.Item { let notFoundError = NotFoundError("identity: \(identity), location: \(location ?? "none")") @@ -484,8 +487,7 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { if let location { // A package identity can be associated with multiple repository URLs matches = packagesCollections.packages.filter { CanonicalPackageLocation($0.location) == CanonicalPackageLocation(location) } - } - else { + } else { matches = packagesCollections.packages } guard let package = matches.first else { @@ -493,7 +495,8 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { } return PackageCollectionsModel.PackageSearchResult.Item( package: package, - collections: packagesCollections.collections) + collections: packagesCollections.collections + ) } @@ -534,33 +537,39 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable { ) } } - return .init(identity: pair.package.identity, - location: pair.package.location, - summary: pair.package.summary, - versions: versions, - collections: Array(pair.collections)) + return .init( + identity: pair.package.identity, + location: pair.package.location, + summary: pair.package.summary, + versions: versions, + collections: Array(pair.collections) + ) } return Model.TargetListItem(target: pair.target, packages: targetPackages) } } - internal static func mergedPackageMetadata(package: Model.Package, - basicMetadata: Model.PackageBasicMetadata?) -> Model.Package { + internal static func mergedPackageMetadata( + package: Model.Package, + basicMetadata: Model.PackageBasicMetadata? + ) -> Model.Package { // This dictionary contains recent releases and might not contain everything that's in package.versions. let basicVersionMetadata = basicMetadata.map { Dictionary($0.versions.map { ($0.version, $0) }, uniquingKeysWith: { first, _ in first }) } ?? [:] var versions = package.versions.map { packageVersion -> Model.Package.Version in let versionMetadata = basicVersionMetadata[packageVersion.version] - return .init(version: packageVersion.version, - title: versionMetadata?.title ?? packageVersion.title, - summary: versionMetadata?.summary ?? packageVersion.summary, - manifests: packageVersion.manifests, - defaultToolsVersion: packageVersion.defaultToolsVersion, - verifiedCompatibility: packageVersion.verifiedCompatibility, - license: packageVersion.license, - author: versionMetadata?.author ?? packageVersion.author, - signer: packageVersion.signer, - createdAt: versionMetadata?.createdAt ?? packageVersion.createdAt) + return .init( + version: packageVersion.version, + title: versionMetadata?.title ?? packageVersion.title, + summary: versionMetadata?.summary ?? packageVersion.summary, + manifests: packageVersion.manifests, + defaultToolsVersion: packageVersion.defaultToolsVersion, + verifiedCompatibility: packageVersion.verifiedCompatibility, + license: packageVersion.license, + author: versionMetadata?.author ?? packageVersion.author, + signer: packageVersion.signer, + createdAt: versionMetadata?.createdAt ?? packageVersion.createdAt + ) } versions.sort(by: >) diff --git a/Sources/PackageCollections/PackageIndex+Configuration.swift b/Sources/PackageCollections/PackageIndex+Configuration.swift index 80083ff9fc5..394c669d56c 100644 --- a/Sources/PackageCollections/PackageIndex+Configuration.swift +++ b/Sources/PackageCollections/PackageIndex+Configuration.swift @@ -19,10 +19,10 @@ public struct PackageIndexConfiguration: Equatable { public var cacheDirectory: AbsolutePath public var cacheTTLInSeconds: Int public var cacheMaxSizeInMegabytes: Int - + // TODO: rdar://87575573 remove feature flag public internal(set) var enabled = ProcessInfo.processInfo.environment["SWIFTPM_ENABLE_PACKAGE_INDEX"] == "1" - + public init( url: URL? = nil, searchResultMaxItemsCount: Int? = nil, @@ -52,7 +52,7 @@ public struct PackageIndexConfigurationStorage { self.encoder = JSONEncoder.makeWithDefaults() self.decoder = JSONDecoder.makeWithDefaults() } - + public func load() throws -> PackageIndexConfiguration { guard self.fileSystem.exists(self.path) else { return .init() @@ -73,7 +73,7 @@ public struct PackageIndexConfigurationStorage { let buffer = try encoder.encode(container) try self.fileSystem.writeFileContents(self.path, data: buffer) } - + @discardableResult public func update(with handler: (inout PackageIndexConfiguration) throws -> Void) throws -> PackageIndexConfiguration { let configuration = try self.load() @@ -124,7 +124,7 @@ private extension PackageIndexConfiguration { throw SerializationError.invalidURL(urlString) } } - + let cacheDirectory: AbsolutePath? switch from.cacheDirectory { case .none: diff --git a/Sources/PackageCollections/PackageIndex.swift b/Sources/PackageCollections/PackageIndex.swift index 9e0f9bb9d8e..fb42603e2ef 100644 --- a/Sources/PackageCollections/PackageIndex.swift +++ b/Sources/PackageCollections/PackageIndex.swift @@ -22,11 +22,11 @@ struct PackageIndex: PackageIndexProtocol, Closable { private let httpClient: LegacyHTTPClient private let callbackQueue: DispatchQueue private let observabilityScope: ObservabilityScope - + private let decoder: JSONDecoder private let cache: SQLiteBackedCache? - + var isEnabled: Bool { self.configuration.enabled && self.configuration.url != .none } @@ -41,9 +41,9 @@ struct PackageIndex: PackageIndexProtocol, Closable { self.httpClient = customHTTPClient ?? Self.makeDefaultHTTPClient() self.callbackQueue = callbackQueue self.observabilityScope = observabilityScope - + self.decoder = JSONDecoder.makeWithDefaults() - + if configuration.cacheTTLInSeconds > 0 { var cacheConfig = SQLiteBackedCacheConfiguration() cacheConfig.maxSizeInMegabytes = configuration.cacheMaxSizeInMegabytes @@ -56,7 +56,7 @@ struct PackageIndex: PackageIndexProtocol, Closable { self.cache = nil } } - + func close() throws { try self.cache?.close() } @@ -67,7 +67,8 @@ struct PackageIndex: PackageIndexProtocol, Closable { ) async throws -> PackageCollectionsModel.PackageMetadata { let url = try await self.urlIfConfigured() if let cached = try? self.cache?.get(key: identity.description), - cached.dispatchTime + DispatchTimeInterval.seconds(self.configuration.cacheTTLInSeconds) > DispatchTime.now() { + cached.dispatchTime + DispatchTimeInterval.seconds(self.configuration.cacheTTLInSeconds) > DispatchTime.now() + { return (package: cached.package, collections: [], provider: self.createContext(host: url.host, error: nil)) } @@ -99,7 +100,7 @@ struct PackageIndex: PackageIndexProtocol, Closable { throw PackageIndexError.invalidResponse(metadataURL, "Invalid status code: \(response.statusCode)") } } - + func findPackages( _ query: String ) async throws -> PackageCollectionsModel.PackageSearchResult { @@ -109,7 +110,7 @@ struct PackageIndex: PackageIndexProtocol, Closable { } urlComponents.path = (urlComponents.path.last == "/" ? "" : "/") + "search" urlComponents.queryItems = [ - URLQueryItem(name: "q", value: query), + URLQueryItem(name: "q", value: query) ] // TODO: rdar://87582621 call package index's search API @@ -177,7 +178,7 @@ struct PackageIndex: PackageIndexProtocol, Closable { } return url } - + private func createContext(host: String?, error: Error?) -> PackageMetadataProviderContext? { let name = host ?? "package index" return PackageMetadataProviderContext( @@ -187,7 +188,7 @@ struct PackageIndex: PackageIndexProtocol, Closable { isAuthTokenConfigured: true ) } - + private static func makeDefaultHTTPClient() -> LegacyHTTPClient { let client = LegacyHTTPClient() // TODO: make these defaults configurable? diff --git a/Sources/PackageCollections/PackageIndexAndCollections.swift b/Sources/PackageCollections/PackageIndexAndCollections.swift index 1b8ffe48bf1..84c3dbf58c0 100644 --- a/Sources/PackageCollections/PackageIndexAndCollections.swift +++ b/Sources/PackageCollections/PackageIndexAndCollections.swift @@ -21,7 +21,7 @@ public struct PackageIndexAndCollections: Closable { private let index: PackageIndexProtocol private let collections: PackageCollectionsProtocol private let observabilityScope: ObservabilityScope - + public init( indexConfiguration: PackageIndexConfiguration = .init(), collectionsConfiguration: PackageCollections.Configuration = .init(), @@ -43,7 +43,7 @@ public struct PackageIndexAndCollections: Closable { managed: true ) ) - + self.index = index self.collections = PackageCollections( configuration: collectionsConfiguration, @@ -53,13 +53,13 @@ public struct PackageIndexAndCollections: Closable { ) self.observabilityScope = observabilityScope } - + init(index: PackageIndexProtocol, collections: PackageCollectionsProtocol, observabilityScope: ObservabilityScope) { self.index = index self.collections = collections self.observabilityScope = observabilityScope } - + public func close() throws { if let index = self.index as? Closable { try index.close() @@ -68,16 +68,15 @@ public struct PackageIndexAndCollections: Closable { try collections.close() } } - + // MARK: - Package collection specific APIs - + public func listCollections( identifiers: Set? = nil ) async throws -> [PackageCollectionsModel.Collection] { try await self.collections.listCollections(identifiers: identifiers) } - public func refreshCollections() async throws -> [PackageCollectionsModel.CollectionSource] { try await self.collections.refreshCollections() } @@ -97,7 +96,7 @@ public struct PackageIndexAndCollections: Closable { trustConfirmationProvider: trustConfirmationProvider ) } - + public func removeCollection( _ source: PackageCollectionsModel.CollectionSource ) async throws { @@ -115,7 +114,7 @@ public struct PackageIndexAndCollections: Closable { ) async throws -> PackageCollectionsModel.PackageSearchResult { try await self.collections.listPackages(collections: collections) } - + public func listTargets( collections: Set? = nil ) async throws -> PackageCollectionsModel.TargetListResult { @@ -134,14 +133,13 @@ public struct PackageIndexAndCollections: Closable { ) } - // MARK: - Package index specific APIs /// Indicates if package index is configured. public func isIndexEnabled() -> Bool { self.index.isEnabled } - + public func listPackagesInIndex( offset: Int, limit: Int @@ -149,7 +147,6 @@ public struct PackageIndexAndCollections: Closable { try await self.index.listPackages(offset: offset, limit: limit) } - // MARK: - APIs that make use of both package index and collections /// Returns metadata for the package identified by the given `PackageIdentity`, using package index (if configured) @@ -179,7 +176,6 @@ public struct PackageIndexAndCollections: Closable { // must belong to at least one collection. async let collectionsResult = self.collections.getPackageMetadata(identity: identity, location: location, collections: collections) - do { let indexPackageMetadata = try await indexResult return PackageCollectionsModel.PackageMetadata( @@ -227,12 +223,16 @@ public struct PackageIndexAndCollections: Closable { do { let collectionsSearchResult = try await pendingcollectionPackages - let indexItems = Dictionary(uniqueKeysWithValues: indexSearchResult.items.map { - (SearchResultItemKey(identity: $0.package.identity, location: $0.package.location), $0) - }) - let collectionItems = Dictionary(uniqueKeysWithValues: collectionsSearchResult.items.map { - (SearchResultItemKey(identity: $0.package.identity, location: $0.package.location), $0) - }) + let indexItems = Dictionary( + uniqueKeysWithValues: indexSearchResult.items.map { + (SearchResultItemKey(identity: $0.package.identity, location: $0.package.location), $0) + } + ) + let collectionItems = Dictionary( + uniqueKeysWithValues: collectionsSearchResult.items.map { + (SearchResultItemKey(identity: $0.package.identity, location: $0.package.location), $0) + } + ) // An array of combined results, with index items listed first. var items = [PackageCollectionsModel.PackageSearchResult.Item]() @@ -294,7 +294,7 @@ public struct PackageIndexAndCollections: Closable { } } } - + private enum Source: Hashable { case index case collections @@ -303,10 +303,10 @@ public struct PackageIndexAndCollections: Closable { struct PackageIndexMetadataProvider: PackageMetadataProvider, Closable { typealias ProviderContainer = (provider: PackageMetadataProvider, managed: Bool) - + let index: PackageIndex let alternativeContainer: ProviderContainer - + var alternative: PackageMetadataProvider { self.alternativeContainer.provider } @@ -321,7 +321,7 @@ struct PackageIndexMetadataProvider: PackageMetadataProvider, Closable { return await self.alternative.get(identity: identity, location: location) } } - + func close() throws { guard self.alternativeContainer.managed else { return diff --git a/Sources/PackageCollections/Providers/GitHubPackageMetadataProvider.swift b/Sources/PackageCollections/Providers/GitHubPackageMetadataProvider.swift index 9aee9b67155..474d191aa59 100644 --- a/Sources/PackageCollections/Providers/GitHubPackageMetadataProvider.swift +++ b/Sources/PackageCollections/Providers/GitHubPackageMetadataProvider.swift @@ -173,28 +173,28 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider, Closable { return self.metadataErrorResponse(error, apiHost: baseURL.host) } } - + private func metadataErrorResponse( _ error: Error, apiHost: String? ) -> (Result, PackageMetadataProviderContext?) { return (.failure(error), self.createContext(apiHost: apiHost, error: error)) } - + private func createContext(apiHost: String?, error: Error?) -> PackageMetadataProviderContext? { // We can't do anything if we can't determine API host guard let apiHost else { return nil } - + let authTokenType = self.getAuthTokenType(for: apiHost) let isAuthTokenConfigured = self.configuration.authTokens()?[authTokenType] != nil - + // This provider should only deal with GitHub token type guard case .github(let host) = authTokenType else { return nil } - + guard let error else { // It's possible for the request to complete successfully without auth token configured, in // which case we will hit the API limit much more easily, so we should always communicate @@ -205,7 +205,7 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider, Closable { isAuthTokenConfigured: isAuthTokenConfigured ) } - + switch error { case let error as GitHubPackageMetadataProviderError: guard let providerError = PackageMetadataProviderError.from(error) else { @@ -213,7 +213,7 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider, Closable { // assume this provider cannot be used for the package. return nil } - + return PackageMetadataProviderContext( name: host, authTokenType: authTokenType, @@ -226,7 +226,7 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider, Closable { return nil } } - + private func getAuthTokenType(for host: String) -> AuthTokenType { let host = host.hasPrefix(Self.apiHostPrefix) ? String(host.dropFirst(Self.apiHostPrefix.count)) : host return .github(host) @@ -239,7 +239,8 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider, Closable { if let match = regex.firstMatch(in: url, options: [], range: NSRange(location: 0, length: url.count)) { if let hostRange = Range(match.range(at: 1), in: url), let ownerRange = Range(match.range(at: 2), in: url), - let repoRange = Range(match.range(at: 3), in: url) { + let repoRange = Range(match.range(at: 3), in: url) + { let host = String(url[hostRange]) let owner = String(url[ownerRange]) let repo = String(url[repoRange]) @@ -290,7 +291,7 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider, Closable { disableCache: Bool = false, cacheDir: AbsolutePath? = nil, cacheTTLInSeconds: Int? = nil, - cacheSizeInMegabytes: Int? = nil + cacheSizeInMegabytes: Int? = nil ) { self.authTokens = authTokens self.apiLimitWarningThreshold = apiLimitWarningThreshold ?? 5 @@ -397,7 +398,7 @@ extension GitHubPackageMetadataProvider { case publishedAt = "published_at" case author } - + fileprivate struct Author: Codable { let login: String let url: URL? diff --git a/Sources/PackageCollections/Providers/JSONPackageCollectionProvider.swift b/Sources/PackageCollections/Providers/JSONPackageCollectionProvider.swift index 4e24bb717e0..58da95e5000 100644 --- a/Sources/PackageCollections/Providers/JSONPackageCollectionProvider.swift +++ b/Sources/PackageCollections/Providers/JSONPackageCollectionProvider.swift @@ -34,9 +34,9 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider { // TODO: This can be removed when the `Security` framework APIs that the `PackageCollectionsSigning` // module depends on are available on all Apple platforms. #if os(macOS) || os(Linux) || os(Windows) || os(Android) || os(FreeBSD) - static let isSignatureCheckSupported = true + static let isSignatureCheckSupported = true #else - static let isSignatureCheckSupported = false + static let isSignatureCheckSupported = false #endif static let defaultCertPolicyKeys: [CertificatePolicyKey] = [.default] @@ -63,12 +63,13 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider { self.fileSystem = fileSystem self.observabilityScope = observabilityScope self.httpClient = customHTTPClient ?? Self.makeDefaultHTTPClient() - self.signatureValidator = customSignatureValidator ?? PackageCollectionSigning( - trustedRootCertsDir: configuration.trustedRootCertsDir ?? - (try? fileSystem.swiftPMConfigurationDirectory.appending("trust-root-certs").asURL) ?? Basics.AbsolutePath.root.asURL, - additionalTrustedRootCerts: sourceCertPolicy.allRootCerts.map { Array($0) }, - observabilityScope: observabilityScope - ) + self.signatureValidator = + customSignatureValidator + ?? PackageCollectionSigning( + trustedRootCertsDir: configuration.trustedRootCertsDir ?? (try? fileSystem.swiftPMConfigurationDirectory.appending("trust-root-certs").asURL) ?? Basics.AbsolutePath.root.asURL, + additionalTrustedRootCerts: sourceCertPolicy.allRootCerts.map { Array($0) }, + observabilityScope: observabilityScope + ) self.sourceCertPolicy = sourceCertPolicy self.decoder = JSONDecoder.makeWithDefaults() } @@ -102,18 +103,22 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider { response = try await self.httpClient.head(source.url, headers: headers, options: headOptions) } catch HTTPClientError.badResponseStatusCode(let statusCode) { if statusCode == 404 { - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .collectionNotFound(source.url) } - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .collectionUnavailable(source.url, statusCode) } guard let contentLength = response.headers.get("Content-Length").first.flatMap(Int64.init) else { - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .invalidResponse(source.url, "Missing Content-Length header") } guard contentLength <= self.configuration.maximumSizeInBytes else { - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .responseTooLarge(source.url, contentLength) } // next do a get request to get the actual content @@ -125,10 +130,12 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider { getResponse = try await self.httpClient.get(source.url, headers: headers, options: getOptions) } catch HTTPClientError.badResponseStatusCode(let statusCode) { if statusCode == 404 { - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .collectionNotFound(source.url) } - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .collectionUnavailable(source.url, statusCode) } @@ -137,19 +144,24 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider { // TODO: store bad actors to prevent server DoS guard let contentLength = getResponse.headers.get("Content-Length").first.flatMap(Int64.init) else { - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .invalidResponse(source.url, "Missing Content-Length header") } guard contentLength < self.configuration.maximumSizeInBytes else { - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .responseTooLarge(source.url, contentLength) } guard let body = getResponse.body else { - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .invalidResponse(source.url, "Body is empty") } - let certPolicyKeys = self.sourceCertPolicy.certificatePolicyKeys(for: source) ?? Self + let certPolicyKeys = + self.sourceCertPolicy.certificatePolicyKeys(for: source) + ?? Self .defaultCertPolicyKeys return try await self.decodeAndRunSignatureCheck( source: source, @@ -241,7 +253,8 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider { signature: Model.SignatureData? ) throws -> Model.Collection { if let errors = self.validator.validate(collection: collection)?.errors() { - throw JSONPackageCollectionProviderError + throw + JSONPackageCollectionProviderError .invalidCollection("\(errors.map(\.message).joined(separator: " "))") } @@ -255,38 +268,40 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider { } let manifests: [ToolsVersion: Model.Package.Version.Manifest] = - try Dictionary(throwingUniqueKeysWithValues: version.manifests.compactMap { key, value in - guard let keyToolsVersion = ToolsVersion(string: key), - let manifestToolsVersion = ToolsVersion(string: value.toolsVersion) - else { - return nil - } - - let targets = value.targets.map { Model.Target(name: $0.name, moduleName: $0.moduleName) } - if targets.count != value.targets.count { - serializationOkay = false - } - let products = value.products - .compactMap { Model.Product(from: $0, packageTargets: targets) } - if products.count != value.products.count { - serializationOkay = false - } - let minimumPlatformVersions: [PackageModel.SupportedPlatform]? = value - .minimumPlatformVersions? - .compactMap { PackageModel.SupportedPlatform(from: $0) } - if minimumPlatformVersions?.count != value.minimumPlatformVersions?.count { - serializationOkay = false - } - - let manifest = Model.Package.Version.Manifest( - toolsVersion: manifestToolsVersion, - packageName: value.packageName, - targets: targets, - products: products, - minimumPlatformVersions: minimumPlatformVersions + try Dictionary( + throwingUniqueKeysWithValues: version.manifests.compactMap { key, value in + guard let keyToolsVersion = ToolsVersion(string: key), + let manifestToolsVersion = ToolsVersion(string: value.toolsVersion) + else { + return nil + } + + let targets = value.targets.map { Model.Target(name: $0.name, moduleName: $0.moduleName) } + if targets.count != value.targets.count { + serializationOkay = false + } + let products = value.products + .compactMap { Model.Product(from: $0, packageTargets: targets) } + if products.count != value.products.count { + serializationOkay = false + } + let minimumPlatformVersions: [PackageModel.SupportedPlatform]? = value + .minimumPlatformVersions? + .compactMap { PackageModel.SupportedPlatform(from: $0) } + if minimumPlatformVersions?.count != value.minimumPlatformVersions?.count { + serializationOkay = false + } + + let manifest = Model.Package.Version.Manifest( + toolsVersion: manifestToolsVersion, + packageName: value.packageName, + targets: targets, + products: products, + minimumPlatformVersions: minimumPlatformVersions + ) + return (keyToolsVersion, manifest) + } ) - return (keyToolsVersion, manifest) - }) if manifests.count != version.manifests.count { serializationOkay = false } @@ -304,7 +319,7 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider { let signer: Model.Signer? if let versionSigner = version.signer, - let signerType = Model.SignerType(rawValue: versionSigner.type.lowercased()) + let signerType = Model.SignerType(rawValue: versionSigner.type.lowercased()) { signer = .init( type: signerType, @@ -432,7 +447,7 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider { maximumMinorVersionCount: Int? = nil ) { // TODO: where should we read defaults from? - self.maximumSizeInBytes = maximumSizeInBytes ?? 5_000_000 // 5MB + self.maximumSizeInBytes = maximumSizeInBytes ?? 5_000_000 // 5MB self.trustedRootCertsDir = trustedRootCertsDir self.validator = JSONModel.Validator.Configuration( maximumPackageCount: maximumPackageCount, @@ -563,7 +578,7 @@ extension PackageModel.Platform { extension Model.Compatibility { fileprivate init?(from: JSONModel.Compatibility) { guard let platform = PackageModel.Platform(from: from.platform), - let swiftVersion = SwiftLanguageVersion(string: from.swiftVersion) + let swiftVersion = SwiftLanguageVersion(string: from.swiftVersion) else { return nil } diff --git a/Sources/PackageCollections/Storage/FilePackageCollectionsSourcesStorage.swift b/Sources/PackageCollections/Storage/FilePackageCollectionsSourcesStorage.swift index ddc24c23f2b..f6ec20cd737 100644 --- a/Sources/PackageCollections/Storage/FilePackageCollectionsSourcesStorage.swift +++ b/Sources/PackageCollections/Storage/FilePackageCollectionsSourcesStorage.swift @@ -163,8 +163,12 @@ private extension Model.CollectionSource { func source() -> StorageModel.Source { switch self.type { case .json: - return .init(type: StorageModel.SourceType.json.rawValue, value: self.url.absoluteString, - isTrusted: self.isTrusted, skipSignatureCheck: self.skipSignatureCheck) + return .init( + type: StorageModel.SourceType.json.rawValue, + value: self.url.absoluteString, + isTrusted: self.isTrusted, + skipSignatureCheck: self.skipSignatureCheck + ) } } } diff --git a/Sources/PackageCollections/Storage/PackageCollectionsSourcesStorage.swift b/Sources/PackageCollections/Storage/PackageCollectionsSourcesStorage.swift index beaa3825eec..5a9c7941c98 100644 --- a/Sources/PackageCollections/Storage/PackageCollectionsSourcesStorage.swift +++ b/Sources/PackageCollections/Storage/PackageCollectionsSourcesStorage.swift @@ -22,8 +22,10 @@ public protocol PackageCollectionsSourcesStorage { /// - source: The `PackageCollectionSource` to add /// - order: Optional. The order that the source should take after being added. /// By default the new source is appended to the end (i.e., the least relevant order). - func add(source: PackageCollectionsModel.CollectionSource, - order: Int?) async throws + func add( + source: PackageCollectionsModel.CollectionSource, + order: Int? + ) async throws /// Removes the given source. /// diff --git a/Sources/PackageCollections/Storage/SQLitePackageCollectionsStorage.swift b/Sources/PackageCollections/Storage/SQLitePackageCollectionsStorage.swift index 295a496deb7..d23bbc9d038 100644 --- a/Sources/PackageCollections/Storage/SQLitePackageCollectionsStorage.swift +++ b/Sources/PackageCollections/Storage/SQLitePackageCollectionsStorage.swift @@ -27,7 +27,7 @@ import protocol TSCBasic.Closable final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable { private static let packageCollectionsTableName = "package_collections" private static let packagesFTSName = "fts_packages" - private static let targetsFTSNameV0 = "fts_targets" // TODO: remove as this has been replaced by v1 + private static let targetsFTSNameV0 = "fts_targets" // TODO: remove as this has been replaced by v1 private static let targetsFTSNameV1 = "fts_targets_1" let fileSystem: FileSystem @@ -163,7 +163,7 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable let query = "DELETE FROM \(Self.packageCollectionsTableName) WHERE key = ?;" try self.executeStatement(query) { statement -> Void in let bindings: [SQLite.SQLiteValue] = [ - .string(identifier.databaseKey()), + .string(identifier.databaseKey()) ] try statement.bind(bindings) try statement.step() @@ -208,7 +208,7 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable if let identifiers { var index = 0 while index < identifiers.count { - let slice = identifiers[index ..< min(index + self.configuration.batchSize, identifiers.count)] + let slice = identifiers[index..)]()) { result, match in var entry = result.removeValue(forKey: match.package) if entry == nil { - guard let package = collectionDict[match.collection].flatMap({ collection in - collection.packages.first(where: { $0.identity == match.package }) - }) else { + guard + let package = collectionDict[match.collection].flatMap({ collection in + collection.packages.first(where: { $0.identity == match.package }) + }) + else { return } entry = (package, .init()) @@ -347,9 +353,11 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable // FTS results are not sorted by relevance at all (FTS5 supports ORDER BY rank but FTS4 requires additional SQL function) // Sort by package name for consistent ordering in results - return Model.PackageSearchResult(items: packageCollections.sorted { $0.value.package.displayName < $1.value.package.displayName }.map { entry in - .init(package: entry.value.package, collections: Array(entry.value.collections)) - }) + return Model.PackageSearchResult( + items: packageCollections.sorted { $0.value.package.displayName < $1.value.package.displayName }.map { entry in + .init(package: entry.value.package, collections: Array(entry.value.collections)) + } + ) } func findPackage( @@ -385,7 +393,8 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable while let row = try statement.step() { if let collectionData = Data(base64Encoded: row.string(at: 0)), - let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData) { + let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData) + { matchingCollections.insert(collection) } } @@ -434,21 +443,23 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable func buildResult() -> Model.TargetSearchResult { // Sort by target name for consistent ordering in results - return Model.TargetSearchResult(items: targetPackageVersions.sorted { $0.key.name < $1.key.name }.map { target, packageVersions in - let targetPackages: [Model.TargetListItem.Package] = packageVersions.compactMap { identity, versions in - guard let packageEntry = packageCollections[identity] else { - return nil + return Model.TargetSearchResult( + items: targetPackageVersions.sorted { $0.key.name < $1.key.name }.map { target, packageVersions in + let targetPackages: [Model.TargetListItem.Package] = packageVersions.compactMap { identity, versions in + guard let packageEntry = packageCollections[identity] else { + return nil + } + return Model.TargetListItem.Package( + identity: packageEntry.package.identity, + location: packageEntry.package.location, + summary: packageEntry.package.summary, + versions: Array(versions).sorted(by: >), + collections: Array(packageEntry.collections) + ) } - return Model.TargetListItem.Package( - identity: packageEntry.package.identity, - location: packageEntry.package.location, - summary: packageEntry.package.summary, - versions: Array(versions).sorted(by: >), - collections: Array(packageEntry.collections) - ) + return Model.TargetListItem(target: target, packages: targetPackages) } - return Model.TargetListItem(target: target, packages: targetPackages) - }) + ) } guard try self.shouldUseSearchIndices() else { @@ -537,13 +548,16 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable while let row = try statement.step() { if let collectionData = Data(base64Encoded: row.string(at: 0)), - let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData) { - matches.append(( - collection: collection, - package: PackageIdentity.plain(row.string(at: 1)), - packageLocation: row.string(at: 2), - targetName: row.string(at: 3) - )) + let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData) + { + matches.append( + ( + collection: collection, + package: PackageIdentity.plain(row.string(at: 1)), + packageLocation: row.string(at: 2), + targetName: row.string(at: 3) + ) + ) matchingCollections.insert(collection) } } @@ -559,13 +573,16 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable while let row = try statement.step() { if let collectionData = Data(base64Encoded: row.string(at: 0)), - let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData) { - matches.append(( - collection: collection, - package: PackageIdentity(urlString: row.string(at: 1)), - packageLocation: row.string(at: 1), - targetName: row.string(at: 2) - )) + let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData) + { + matches.append( + ( + collection: collection, + package: PackageIdentity(urlString: row.string(at: 1)), + packageLocation: row.string(at: 1), + targetName: row.string(at: 2) + ) + ) matchingCollections.insert(collection) } } @@ -587,9 +604,11 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable matches.filter { collectionDict.keys.contains($0.collection) }.forEach { match in var packageEntry = packageCollections.removeValue(forKey: match.package) if packageEntry == nil { - guard let package = collectionDict[match.collection].flatMap({ collection in - collection.packages.first(where: { $0.identity == match.package || $0.location == match.packageLocation }) - }) else { + guard + let package = collectionDict[match.collection].flatMap({ collection in + collection.packages.first(where: { $0.identity == match.package || $0.location == match.packageLocation }) + }) + else { return } packageEntry = (package, .init()) @@ -763,7 +782,7 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable DispatchQueue.sharedConcurrent.async(group: nil, qos: .background, flags: .assignCurrentContext) { do { - try self.populateTargetTrieLock.withLock { // Prevent race to populate targetTrie + try self.populateTargetTrieLock.withLock { // Prevent race to populate targetTrie // Exit early if we've already done the computation before guard self.targetTrieReady == nil else { return @@ -788,20 +807,21 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable try self.executeStatement(queryV1) { statement in while let row = try statement.step() { #if os(Linux) - // lock not required since executeStatement locks - guard case .connected = self.state else { - return - } + // lock not required since executeStatement locks + guard case .connected = self.state else { + return + } #else - guard case .connected = (try self.withStateLock { self.state }) else { - return - } + guard case .connected = (try self.withStateLock { self.state }) else { + return + } #endif let targetName = row.string(at: 3) if let collectionData = Data(base64Encoded: row.string(at: 0)), - let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData) { + let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData) + { let collectionPackage = CollectionPackage( collection: collection, package: PackageIdentity.plain(row.string(at: 1)), @@ -817,21 +837,22 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable try self.executeStatement(queryV0) { statement in while let row = try statement.step() { #if os(Linux) - // lock not required since executeStatement locks - guard case .connected = self.state else { - return - } + // lock not required since executeStatement locks + guard case .connected = self.state else { + return + } #else - guard case .connected = (try self.withStateLock { self.state }) else { - return - } + guard case .connected = (try self.withStateLock { self.state }) else { + return + } #endif let targetName = row.string(at: 2) if let collectionData = Data(base64Encoded: row.string(at: 0)), - let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData), - !collectionsProcessed.contains(collection) { + let collection = try? self.decoder.decode(Model.CollectionIdentifier.self, from: collectionData), + !collectionsProcessed.contains(collection) + { let collectionPackage = CollectionPackage( collection: collection, package: PackageIdentity(urlString: row.string(at: 1)), @@ -912,64 +933,64 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable // FIXME: workaround linux sqlite concurrency issues causing CI failures #if os(Linux) - return try self.withStateLock { - try body(db) - } + return try self.withStateLock { + try body(db) + } #else - return try body(db) + return try body(db) #endif } private func createSchemaIfNecessary(db: SQLite) throws { let table = """ - CREATE TABLE IF NOT EXISTS \(Self.packageCollectionsTableName) ( - key STRING PRIMARY KEY NOT NULL, - value BLOB NOT NULL - ); - """ - try db.exec(query: table) - - #if os(Android) - // FTS queries for strings containing hyphens isn't working in SQLite on - // Android, so disable for now. - self.useSearchIndices.put(false) - #else - do { - let ftsPackages = """ - CREATE VIRTUAL TABLE IF NOT EXISTS \(Self.packagesFTSName) USING fts4( - collection_id_blob_base64, id, version, name, repository_url, summary, keywords, products, targets, - notindexed=collection_id_blob_base64, - tokenize=unicode61 - ); - """ - try db.exec(query: ftsPackages) - - // We don't insert to this anymore but keeping it for queries to work - let ftsTargetsV0 = """ - CREATE VIRTUAL TABLE IF NOT EXISTS \(Self.targetsFTSNameV0) USING fts4( - collection_id_blob_base64, package_repository_url, name, - notindexed=collection_id_blob_base64, - tokenize=unicode61 - ); - """ - try db.exec(query: ftsTargetsV0) - - let ftsTargetsV1 = """ - CREATE VIRTUAL TABLE IF NOT EXISTS \(Self.targetsFTSNameV1) USING fts4( - collection_id_blob_base64, package_id, package_repository_url, name, - notindexed=collection_id_blob_base64, - tokenize=unicode61 + CREATE TABLE IF NOT EXISTS \(Self.packageCollectionsTableName) ( + key STRING PRIMARY KEY NOT NULL, + value BLOB NOT NULL ); """ - try db.exec(query: ftsTargetsV1) + try db.exec(query: table) - self.useSearchIndices.put(true) - } catch { - // We can use FTS3 tables but queries yield different results when run on different - // platforms. This could be because of SQLite version perhaps? But since we can't get - // consistent results we will not fallback to FTS3 and just give up if FTS4 is not available. + #if os(Android) + // FTS queries for strings containing hyphens isn't working in SQLite on + // Android, so disable for now. self.useSearchIndices.put(false) - } + #else + do { + let ftsPackages = """ + CREATE VIRTUAL TABLE IF NOT EXISTS \(Self.packagesFTSName) USING fts4( + collection_id_blob_base64, id, version, name, repository_url, summary, keywords, products, targets, + notindexed=collection_id_blob_base64, + tokenize=unicode61 + ); + """ + try db.exec(query: ftsPackages) + + // We don't insert to this anymore but keeping it for queries to work + let ftsTargetsV0 = """ + CREATE VIRTUAL TABLE IF NOT EXISTS \(Self.targetsFTSNameV0) USING fts4( + collection_id_blob_base64, package_repository_url, name, + notindexed=collection_id_blob_base64, + tokenize=unicode61 + ); + """ + try db.exec(query: ftsTargetsV0) + + let ftsTargetsV1 = """ + CREATE VIRTUAL TABLE IF NOT EXISTS \(Self.targetsFTSNameV1) USING fts4( + collection_id_blob_base64, package_id, package_repository_url, name, + notindexed=collection_id_blob_base64, + tokenize=unicode61 + ); + """ + try db.exec(query: ftsTargetsV1) + + self.useSearchIndices.put(true) + } catch { + // We can use FTS3 tables but queries yield different results when run on different + // platforms. This could be because of SQLite version perhaps? But since we can't get + // consistent results we will not fallback to FTS3 and just give up if FTS4 is not available. + self.useSearchIndices.put(false) + } #endif try db.exec(query: "PRAGMA journal_mode=WAL;") @@ -1031,7 +1052,7 @@ final class SQLitePackageCollectionsStorage: PackageCollectionsStorage, Closable throw StringError("Maximum attempts reached") } let delay = self.multiplier * intervalInMilliseconds - let jitter = Int.random(in: 0 ... self.randomizationFactor) + let jitter = Int.random(in: 0...self.randomizationFactor) self.attempts += 1 self.multiplier *= 2 return .milliseconds(delay + jitter) diff --git a/Sources/PackageCollections/Storage/Trie.swift b/Sources/PackageCollections/Storage/Trie.swift index 26e5f5f386b..1abf0ea4b3b 100644 --- a/Sources/PackageCollections/Storage/Trie.swift +++ b/Sources/PackageCollections/Storage/Trie.swift @@ -123,7 +123,7 @@ struct Trie { // Construct the new prefix by adding the sub-trie root's character var previousCharacters = prefix - previousCharacters.append(root.value!.lowercased()) // !-safe; see precondition + previousCharacters.append(root.value!.lowercased()) // !-safe; see precondition // The root actually forms a word if root.isTerminating { diff --git a/Sources/PackageCollections/Utility.swift b/Sources/PackageCollections/Utility.swift index 004c390d4f7..abcb79c6936 100644 --- a/Sources/PackageCollections/Utility.swift +++ b/Sources/PackageCollections/Utility.swift @@ -15,7 +15,7 @@ import SourceControl struct MultipleErrors: Error, CustomStringConvertible { let errors: [Error] - + init(_ errors: [Error]) { self.errors = errors } diff --git a/Sources/PackageCollectionsCommand/PackageCollectionsCommand.swift b/Sources/PackageCollectionsCommand/PackageCollectionsCommand.swift index e054d54a71b..d50df509b5f 100644 --- a/Sources/PackageCollectionsCommand/PackageCollectionsCommand.swift +++ b/Sources/PackageCollectionsCommand/PackageCollectionsCommand.swift @@ -266,9 +266,9 @@ public struct PackageCollectionsCommand: AsyncParsableCommand { let license = optionalRow("License", version.license?.type.description) return """ - \(version.version) - \(self.printManifest(defaultManifest))\(manifests)\(compatibility)\(license) - """ + \(version.version) + \(self.printManifest(defaultManifest))\(manifests)\(compatibility)\(license) + """ } private func printManifest(_ manifest: PackageCollectionsModel.Package.Version.Manifest) -> String { @@ -276,17 +276,17 @@ public struct PackageCollectionsCommand: AsyncParsableCommand { let products = optionalRow("Products", manifest.products.isEmpty ? nil : manifest.products.compactMap { $0.name }.joined(separator: ", "), indentationLevel: 3) return """ - Tools Version: \(manifest.toolsVersion.description) - Package Name: \(manifest.packageName) - Modules: \(modules)\(products) - """ + Tools Version: \(manifest.toolsVersion.description) + Package Name: \(manifest.packageName) + Modules: \(modules)\(products) + """ } func run(_ swiftCommandState: SwiftCommandState) async throws { try await withState(swiftCommandState) { collections in let identity = PackageIdentity(urlString: self.packageURL) - do { // assume URL is for a package in an imported collection + do { // assume URL is for a package in an imported collection let result = try await collections.getPackageMetadata(identity: identity, location: self.packageURL, collections: nil) if let versionString = version { @@ -305,20 +305,22 @@ public struct PackageCollectionsCommand: AsyncParsableCommand { let stars = optionalRow("Stars", result.package.watchersCount?.description) let readme = optionalRow("Readme", result.package.readmeURL?.absoluteString) let authors = optionalRow("Authors", result.package.authors?.map { $0.username }.joined(separator: ", ")) - let license = optionalRow("License", result.package.license.map { "\($0.type) (\($0.url))" }) + let license = optionalRow("License", result.package.license.map { "\($0.type) (\($0.url))" }) let languages = optionalRow("Languages", result.package.languages?.joined(separator: ", ")) let latestVersion = optionalRow("\(String(repeating: "-", count: 60))\n\(indent())Latest Version", printVersion(result.package.latestVersion)) if jsonOptions.json { try JSONEncoder.makeWithDefaults().print(result.package) } else { - print(""" - \(description) - Available Versions: \(versions)\(readme)\(license)\(authors)\(stars)\(languages)\(latestVersion) - """) + print( + """ + \(description) + Available Versions: \(versions)\(readme)\(license)\(authors)\(stars)\(languages)\(latestVersion) + """ + ) } } - } catch { // assume URL is for a collection + } catch { // assume URL is for a collection // If a version argument was given, we do not perform the fallback. if version != nil { throw error @@ -340,12 +342,14 @@ public struct PackageCollectionsCommand: AsyncParsableCommand { } else { let signature = optionalRow("Signed By", collection.signature.map { "\($0.certificate.subject.commonName ?? "Unspecified") (\($0.isVerified ? "" : "not ")verified)" }) - print(""" - Name: \(collection.name) - Source: \(collection.source.url)\(description)\(keywords)\(createdAt) - Packages: - \(packages)\(signature) - """) + print( + """ + Name: \(collection.name) + Source: \(collection.source.url)\(description)\(keywords)\(createdAt) + Packages: + \(packages)\(signature) + """ + ) } } catch PackageCollectionError.cannotVerifySignature { throw CollectionsError.cannotVerifySignature diff --git a/Sources/PackageCollectionsModel/PackageCollectionModel+v1.swift b/Sources/PackageCollectionsModel/PackageCollectionModel+v1.swift index 85ba3a5dbb2..ceac99fd79f 100644 --- a/Sources/PackageCollectionsModel/PackageCollectionModel+v1.swift +++ b/Sources/PackageCollectionsModel/PackageCollectionModel+v1.swift @@ -81,7 +81,7 @@ extension PackageCollectionModel.V1.Collection { public struct Package: Equatable, Codable { /// The URL of the package. Currently only Git repository URLs are supported. public let url: URL - + /// Package identity for registry (https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#36-package-identification). public let identity: String? @@ -380,13 +380,13 @@ extension PackageCollectionModel.V1 { /// An plugin product. case plugin - + /// An executable code snippet. case snippet /// A test product. case test - + /// A macro product. case `macro` } @@ -500,10 +500,12 @@ extension PackageCollectionModel.V1 { public let organization: String? /// Creates a `Name` - public init(userID: String?, - commonName: String?, - organizationalUnit: String?, - organization: String?) { + public init( + userID: String?, + commonName: String?, + organizationalUnit: String?, + organization: String? + ) { self.userID = userID self.commonName = commonName self.organizationalUnit = organizationalUnit diff --git a/Sources/PackageCollectionsSigning/CertificatePolicy.swift b/Sources/PackageCollectionsSigning/CertificatePolicy.swift index cc91f68db6b..e0c8538d7c1 100644 --- a/Sources/PackageCollectionsSigning/CertificatePolicy.swift +++ b/Sources/PackageCollectionsSigning/CertificatePolicy.swift @@ -16,11 +16,11 @@ import Foundation import Basics #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import SwiftASN1 -@_implementationOnly import X509 + @_implementationOnly import SwiftASN1 + @_implementationOnly import X509 #else -import SwiftASN1 -import X509 + import SwiftASN1 + import X509 #endif public enum CertificatePolicyKey: Hashable, CustomStringConvertible { @@ -177,7 +177,7 @@ struct DefaultCertificatePolicy: CertificatePolicy { certChain: certChain, trustedRoots: self.trustedRoots, policies: { - _ADPCertificatePolicy() // included for testing + _ADPCertificatePolicy() // included for testing // Check if subject name matches _SubjectNamePolicy( expectedUserID: self.expectedSubjectUserID, @@ -253,7 +253,7 @@ struct ADPSwiftPackageCollectionCertificatePolicy: CertificatePolicy { policies: { // Check for specific markers _ADPSwiftPackageCertificatePolicy() - _ADPCertificatePolicy() // included for testing + _ADPCertificatePolicy() // included for testing // Check if subject name matches _SubjectNamePolicy( expectedUserID: self.expectedSubjectUserID, @@ -329,7 +329,7 @@ struct ADPAppleDistributionCertificatePolicy: CertificatePolicy { policies: { // Check for specific markers _ADPAppleDistributionCertificatePolicy() - _ADPCertificatePolicy() // included for testing + _ADPCertificatePolicy() // included for testing // Check if subject name matches _SubjectNamePolicy( expectedUserID: self.expectedSubjectUserID, @@ -360,9 +360,7 @@ struct _CodeSigningPolicy: VerifierPolicy { ] func chainMeetsPolicyRequirements(chain: UnverifiedCertificateChain) async -> PolicyEvaluationResult { - let isCodeSigning = ( - try? chain.leaf.extensions.extendedKeyUsage?.contains(ExtendedKeyUsage.Usage.codeSigning) - ) ?? false + let isCodeSigning = (try? chain.leaf.extensions.extendedKeyUsage?.contains(ExtendedKeyUsage.Usage.codeSigning)) ?? false guard isCodeSigning else { return .failsToMeetPolicy(reason: "Certificate \(chain.leaf) does not have code signing extended key usage") } @@ -477,7 +475,7 @@ struct _ADPCertificatePolicy: VerifierPolicy { /// Include custom marker extensions (which can be critical) so they would not /// be considered unhandled and cause certificate chain validation to fail. let verifyingCriticalExtensions: [ASN1ObjectIdentifier] = - ASN1ObjectIdentifier.NameAttributes.adpAppleDevelopmentMarkers // included for testing + ASN1ObjectIdentifier.NameAttributes.adpAppleDevelopmentMarkers // included for testing func chainMeetsPolicyRequirements(chain: UnverifiedCertificateChain) async -> PolicyEvaluationResult { // Not policing anything here. This policy is mainly for @@ -508,8 +506,9 @@ struct _ADPSwiftPackageCertificatePolicy: VerifierPolicy { // Package collection can be signed with "Swift Package Collection" // or "Swift Package" certificate - guard chain.leaf.hasExtension(oid: ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageCollectionMarker) - || chain.leaf.hasExtension(oid: ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageMarker) + guard + chain.leaf.hasExtension(oid: ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageCollectionMarker) + || chain.leaf.hasExtension(oid: ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageMarker) else { return .failsToMeetPolicy(reason: "Leaf certificate missing marker OID") } diff --git a/Sources/PackageCollectionsSigning/PackageCollectionSigning.swift b/Sources/PackageCollectionsSigning/PackageCollectionSigning.swift index 0dbc770acbe..530c8db0689 100644 --- a/Sources/PackageCollectionsSigning/PackageCollectionSigning.swift +++ b/Sources/PackageCollectionsSigning/PackageCollectionSigning.swift @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// - import Basics import Dispatch import Foundation @@ -18,13 +17,13 @@ import PackageCollectionsModel import SwiftASN1 #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import _CryptoExtras -@_implementationOnly import Crypto -@_implementationOnly import X509 + @_implementationOnly import _CryptoExtras + @_implementationOnly import Crypto + @_implementationOnly import X509 #else -import _CryptoExtras -import Crypto -import X509 + import _CryptoExtras + import Crypto + import X509 #endif public protocol PackageCollectionSigner { @@ -107,21 +106,23 @@ public actor PackageCollectionSigning: PackageCollectionSigner, PackageCollectio observabilityScope: ObservabilityScope ) { self.trustedRootCertsDir = trustedRootCertsDir - self.additionalTrustedRootCerts = additionalTrustedRootCerts.map { $0.compactMap { - guard let data = Data(base64Encoded: $0) else { - observabilityScope.emit(error: "The certificate \($0) is not in valid base64 encoding") - return nil - } - do { - return try Certificate(derEncoded: Array(data)) - } catch { - observabilityScope.emit( - error: "The certificate \($0) is not in valid DER format", - underlyingError: error - ) - return nil + self.additionalTrustedRootCerts = additionalTrustedRootCerts.map { + $0.compactMap { + guard let data = Data(base64Encoded: $0) else { + observabilityScope.emit(error: "The certificate \($0) is not in valid base64 encoding") + return nil + } + do { + return try Certificate(derEncoded: Array(data)) + } catch { + observabilityScope.emit( + error: "The certificate \($0) is not in valid DER format", + underlyingError: error + ) + return nil + } } - } } + } self.certPolicies = [:] self.encoder = JSONEncoder.makeWithDefaults() @@ -204,7 +205,8 @@ public actor PackageCollectionSigning: PackageCollectionSigner, PackageCollectio let privateKey = try _RSA.Signing.PrivateKey(pemRepresentation: privateKeyPEMString) guard privateKey.keySizeInBits >= Self.minimumRSAKeySizeInBits else { - throw PackageCollectionSigningError + throw + PackageCollectionSigningError .invalidKeySize(minimumBits: Self.minimumRSAKeySizeInBits) } @@ -233,7 +235,7 @@ public actor PackageCollectionSigning: PackageCollectionSigner, PackageCollectio throw PackageCollectionSigningError.invalidSignature } - let certificate = certChain.first! // !-safe because certChain cannot be empty at this point + let certificate = certChain.first! // !-safe because certChain cannot be empty at this point let collectionSignature = Model.Signature( signature: signature, certificate: Model.Signature.Certificate( @@ -262,10 +264,11 @@ public actor PackageCollectionSigning: PackageCollectionSigner, PackageCollectio // Verify the collection embedded in the signature is the same as received // i.e., the signature is associated with the given collection and not another - guard let collectionFromSignature = try? self.decoder.decode( - Model.Collection.self, - from: signature.payload - ), + guard + let collectionFromSignature = try? self.decoder.decode( + Model.Collection.self, + from: signature.payload + ), signedCollection.collection == collectionFromSignature else { throw PackageCollectionSigningError.invalidSignature diff --git a/Sources/PackageCollectionsSigning/Signature.swift b/Sources/PackageCollectionsSigning/Signature.swift index 76e27d45d10..a019e29e43f 100644 --- a/Sources/PackageCollectionsSigning/Signature.swift +++ b/Sources/PackageCollectionsSigning/Signature.swift @@ -26,13 +26,13 @@ import Foundation #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import _CryptoExtras -@_implementationOnly import Crypto -@_implementationOnly import X509 + @_implementationOnly import _CryptoExtras + @_implementationOnly import Crypto + @_implementationOnly import X509 #else -import _CryptoExtras -import Crypto -import X509 + import _CryptoExtras + import Crypto + import X509 #endif // The logic in this source file loosely follows https://www.rfc-editor.org/rfc/rfc7515.html @@ -46,8 +46,8 @@ struct Signature { extension Signature { enum Algorithm: String, Codable { - case RS256 // RSASSA-PKCS1-v1_5 using SHA-256 - case ES256 // ECDSA using P-256 and SHA-256 + case RS256 // RSASSA-PKCS1-v1_5 using SHA-256 + case ES256 // ECDSA using P-256 and SHA-256 } struct Header: Equatable, Codable { @@ -91,7 +91,8 @@ extension Signature { let encodedSignature = signatureData.base64URLEncodedBytes() // Result: header.payload.signature - let bytes = encodedHeader + let bytes = + encodedHeader + .period + encodedPayload + .period @@ -128,7 +129,7 @@ extension Signature { let encodedSignature = parts[2] guard let headerBytes = encodedHeader.base64URLDecodedBytes(), - let header = try? jsonDecoder.decode(Header.self, from: headerBytes) + let header = try? jsonDecoder.decode(Header.self, from: headerBytes) else { throw SignatureError.malformedSignature } @@ -143,13 +144,13 @@ extension Signature { let certChain = try await certChainValidate(certChainData) guard let payloadBytes = encodedPayload.base64URLDecodedBytes(), - let signatureBytes = encodedSignature.base64URLDecodedBytes() + let signatureBytes = encodedSignature.base64URLDecodedBytes() else { throw SignatureError.malformedSignature } // Extract public key from the certificate - let certificate = certChain.first! // !-safe because certChain is not empty at this point + let certificate = certChain.first! // !-safe because certChain is not empty at this point // Verify the key was used to generate the signature let message = Data(encodedHeader) + .period + Data(encodedPayload) let digest = SHA256.hash(data: message) @@ -167,11 +168,13 @@ extension Signature { guard let publicKey = _RSA.Signing.PublicKey(certificate.publicKey) else { throw SignatureError.invalidPublicKey } - guard publicKey.isValidSignature( - .init(rawRepresentation: signatureBytes), - for: digest, - padding: .insecurePKCS1v1_5 - ) else { + guard + publicKey.isValidSignature( + .init(rawRepresentation: signatureBytes), + for: digest, + padding: .insecurePKCS1v1_5 + ) + else { throw SignatureError.invalidSignature } } diff --git a/Sources/PackageCollectionsSigning/Utilities/Base64URL.swift b/Sources/PackageCollectionsSigning/Utilities/Base64URL.swift index bae48bb4c62..9b563854761 100644 --- a/Sources/PackageCollectionsSigning/Utilities/Base64URL.swift +++ b/Sources/PackageCollectionsSigning/Utilities/Base64URL.swift @@ -46,7 +46,7 @@ extension Data { /// /// https://tools.ietf.org/html/rfc4648#page-7 mutating func base64URLUnescape() { - for i in 0 ..< self.count { + for i in 0.. Data { - let container = Container.V2(versionFingerprints: try Dictionary( - throwingUniqueKeysWithValues: packageFingerprints.map { version, fingerprintsForVersion in - let fingerprintsByKind = try Dictionary( - throwingUniqueKeysWithValues: fingerprintsForVersion.map { kind, fingerprintsForKind in - let fingerprintsByContentType = try Dictionary( - throwingUniqueKeysWithValues: fingerprintsForKind.map { contentType, fingerprint in - let origin: String - switch fingerprint.origin { - case .sourceControl(let url): - origin = url.absoluteString - case .registry(let url): - origin = url.absoluteString - } + let container = Container.V2( + versionFingerprints: try Dictionary( + throwingUniqueKeysWithValues: packageFingerprints.map { version, fingerprintsForVersion in + let fingerprintsByKind = try Dictionary( + throwingUniqueKeysWithValues: fingerprintsForVersion.map { kind, fingerprintsForKind in + let fingerprintsByContentType = try Dictionary( + throwingUniqueKeysWithValues: fingerprintsForKind.map { contentType, fingerprint in + let origin: String + switch fingerprint.origin { + case .sourceControl(let url): + origin = url.absoluteString + case .registry(let url): + origin = url.absoluteString + } - let storedFingerprint = Container.V2.StoredFingerprint( - origin: origin, - fingerprint: fingerprint.value, - contentType: .from(contentType: contentType) - ) - return (contentType.description, storedFingerprint) - } - ) - return (kind.rawValue, fingerprintsByContentType) - } - ) - return (version.description, fingerprintsByKind) - } - )) + let storedFingerprint = Container.V2.StoredFingerprint( + origin: origin, + fingerprint: fingerprint.value, + contentType: .from(contentType: contentType) + ) + return (contentType.description, storedFingerprint) + } + ) + return (kind.rawValue, fingerprintsByContentType) + } + ) + return (version.description, fingerprintsByKind) + } + ) + ) return try encoder.encode(container) } } extension Fingerprint.ContentType { - fileprivate static func from(_ storage: StorageModel.Container.V2.StoredFingerprint.ContentType) -> Fingerprint + fileprivate static func from(_ storage: StorageModel.Container.V2.StoredFingerprint.ContentType) + -> Fingerprint .ContentType { switch storage { @@ -361,7 +366,7 @@ extension PackageReference: FingerprintReference { guard case .remoteSourceControl(let sourceControlURL) = self.kind else { throw StringError("Package kind [\(self.kind)] does not support fingerprints") } - + let canonicalLocation = CanonicalPackageLocation(sourceControlURL.absoluteString) // Cannot use hashValue because it is not consistent across executions let locationHash = canonicalLocation.description.sha256Checksum.prefix(8) diff --git a/Sources/PackageFingerprint/PackageFingerprintStorage.swift b/Sources/PackageFingerprint/PackageFingerprintStorage.swift index 397a8e3f308..0991110cf7b 100644 --- a/Sources/PackageFingerprint/PackageFingerprintStorage.swift +++ b/Sources/PackageFingerprint/PackageFingerprintStorage.swift @@ -70,7 +70,7 @@ extension PackageFingerprintStorage { kind: Fingerprint.Kind, contentType: Fingerprint.ContentType, observabilityScope: ObservabilityScope - ) throws -> Fingerprint{ + ) throws -> Fingerprint { let fingerprints = try self.get( package: package, version: version, @@ -88,14 +88,16 @@ extension PackageFingerprintStorage { _ fingerprintsByKindResult: Result<[Fingerprint.Kind: [Fingerprint.ContentType: Fingerprint]], Error>, callback: @escaping (Result) -> Void ) { - callback(fingerprintsByKindResult.tryMap { fingerprintsByKind in - guard let fingerprintsByContentType = fingerprintsByKind[kind], - let fingerprint = fingerprintsByContentType[contentType] - else { - throw PackageFingerprintStorageError.notFound + callback( + fingerprintsByKindResult.tryMap { fingerprintsByKind in + guard let fingerprintsByContentType = fingerprintsByKind[kind], + let fingerprint = fingerprintsByContentType[contentType] + else { + throw PackageFingerprintStorageError.notFound + } + return fingerprint } - return fingerprint - }) + ) } } diff --git a/Sources/PackageGraph/ModuleAliasTracker.swift b/Sources/PackageGraph/ModuleAliasTracker.swift index bb080fb424a..c70ff7bf13e 100644 --- a/Sources/PackageGraph/ModuleAliasTracker.swift +++ b/Sources/PackageGraph/ModuleAliasTracker.swift @@ -31,17 +31,20 @@ struct ModuleAliasTracker { let moduleDependencies = modules.flatMap(\.dependencies) for dep in moduleDependencies { if case let .product(productRef, _) = dep, - let productPkg = productRef.package { + let productPkg = productRef.package + { let productPkgID = PackageIdentity.plain(productPkg) // Track dependency package ID chain addPackageIDChain(parent: package, child: productPkgID) if let aliasList = productRef.moduleAliases { // Track aliases for this product - try addAliases(aliasList, - productID: productRef.identity, - productName: productRef.name, - originPackage: productPkgID, - consumingPackage: package) + try addAliases( + aliasList, + productID: productRef.identity, + productName: productRef.name, + originPackage: productPkgID, + consumingPackage: package + ) } } } @@ -55,12 +58,12 @@ struct ModuleAliasTracker { consumingPackage: PackageIdentity ) throws { if let aliasDict = idToAliasMap[originPackage] { - let existingAliases = aliasDict.values.flatMap{$0}.filter { aliases.keys.contains($0.name) } + let existingAliases = aliasDict.values.flatMap { $0 }.filter { aliases.keys.contains($0.name) } for existingAlias in existingAliases { if let newAlias = aliases[existingAlias.name], newAlias != existingAlias.alias { // Error if there are multiple different aliases specified for // modules in this product - throw PackageGraphError.multipleModuleAliases(module: existingAlias.name, product: productName, package: originPackage.description, aliases: existingAliases.map{$0.alias} + [newAlias]) + throw PackageGraphError.multipleModuleAliases(module: existingAlias.name, product: productName, package: originPackage.description, aliases: existingAliases.map { $0.alias } + [newAlias]) } } } @@ -85,7 +88,7 @@ struct ModuleAliasTracker { // This func should be called once per product mutating func trackModulesPerProduct(product: Product, package: PackageIdentity) { let moduleDeps = product.modules.flatMap(\.dependencies) - var allModuleDeps = product.modules.flatMap{$0.recursiveDependentModules.map{$0.dependencies}}.flatMap{$0} + var allModuleDeps = product.modules.flatMap { $0.recursiveDependentModules.map { $0.dependencies } }.flatMap { $0 } allModuleDeps.append(contentsOf: moduleDeps) for dep in allModuleDeps { if case let .product(depRef, _) = dep { @@ -100,14 +103,16 @@ struct ModuleAliasTracker { productToAllModules[product.identity] = allModulesInProduct } - func validateAndApplyAliases(product: Product, - package: PackageIdentity, - observabilityScope: ObservabilityScope) throws { + func validateAndApplyAliases( + product: Product, + package: PackageIdentity, + observabilityScope: ObservabilityScope + ) throws { guard let modules = idToProductToAllModules[package]?[product.identity] else { return } - let modulesWithAliases = modules.filter{ $0.moduleAliases != nil } + let modulesWithAliases = modules.filter { $0.moduleAliases != nil } for moduleWithAlias in modulesWithAliases { if moduleWithAlias.sources.containsNonSwiftFiles { - let aliasesMsg = moduleWithAlias.moduleAliases?.map{"'\($0.key)' as '\($0.value)'"}.joined(separator: ", ") ?? "" + let aliasesMsg = moduleWithAlias.moduleAliases?.map { "'\($0.key)' as '\($0.value)'" }.joined(separator: ", ") ?? "" observabilityScope.emit(warning: "target '\(moduleWithAlias.name)' for product '\(product.name)' from package '\(package.description)' has module aliases: [\(aliasesMsg)] but may contain non-Swift sources; there might be a conflict among non-Swift symbols") } moduleWithAlias.applyAlias() @@ -153,7 +158,8 @@ struct ModuleAliasTracker { for aliasModel in productAliases { // Alias buffer is used to carry down aliases defined upstream if let existing = aliasBuffer[aliasModel.name], - existing.alias != aliasModel.alias { + existing.alias != aliasModel.alias + { // check to allow only the most downstream alias is added } else { aliasBuffer[aliasModel.name] = aliasModel @@ -161,7 +167,7 @@ struct ModuleAliasTracker { } if let curDirectModules = productToDirectModules[productID] { - var relevantModules = curDirectModules.map{$0.recursiveDependentModules}.flatMap{$0} + var relevantModules = curDirectModules.map { $0.recursiveDependentModules }.flatMap { $0 } relevantModules.append(contentsOf: curDirectModules) for relevantModule in relevantModules { @@ -169,7 +175,8 @@ struct ModuleAliasTracker { appliedAliases.insert(relevantModule.name) relevantModule.addModuleAlias(for: relevantModule.name, as: val) if let prechainVal = aliasBuffer[relevantModule.name], - prechainVal.alias != val { + prechainVal.alias != val + { relevantModule.addPrechainModuleAlias(for: relevantModule.name, as: prechainVal.alias) appliedAliases.insert(prechainVal.alias) relevantModule.addPrechainModuleAlias(for: prechainVal.alias, as: val) @@ -192,9 +199,11 @@ struct ModuleAliasTracker { return } for childID in children { - propagate(productID: childID, - observabilityScope: observabilityScope, - aliasBuffer: &aliasBuffer) + propagate( + productID: childID, + observabilityScope: observabilityScope, + aliasBuffer: &aliasBuffer + ) } } @@ -204,29 +213,33 @@ struct ModuleAliasTracker { return } for childID in children { - merge(productID: childID, - observabilityScope: observabilityScope) + merge( + productID: childID, + observabilityScope: observabilityScope + ) } if let curDirectModules = productToDirectModules[productID] { - let depModules = curDirectModules.map{$0.recursiveDependentModules}.flatMap{$0} - let depModuleAliases = toDictionary(depModules.compactMap{$0.moduleAliases}) + let depModules = curDirectModules.map { $0.recursiveDependentModules }.flatMap { $0 } + let depModuleAliases = toDictionary(depModules.compactMap { $0.moduleAliases }) let depChildModules = dependencyProductModules(of: depModules) - let depChildAliases = toDictionary(depChildModules.compactMap{$0.moduleAliases}) - let depChildPrechainAliases = toDictionary(depChildModules.compactMap{$0.prechainModuleAliases}) - chainModuleAliases(modules: depModules, - checkedModules: depModules, - moduleAliases: depModuleAliases, - childModules: depChildModules, - childAliases: depChildAliases, - childPrechainAliases: depChildPrechainAliases, - observabilityScope: observabilityScope) + let depChildAliases = toDictionary(depChildModules.compactMap { $0.moduleAliases }) + let depChildPrechainAliases = toDictionary(depChildModules.compactMap { $0.prechainModuleAliases }) + chainModuleAliases( + modules: depModules, + checkedModules: depModules, + moduleAliases: depModuleAliases, + childModules: depChildModules, + childAliases: depChildAliases, + childPrechainAliases: depChildPrechainAliases, + observabilityScope: observabilityScope + ) let relevantModules = depModules + curDirectModules - let moduleAliases = toDictionary(relevantModules.compactMap{$0.moduleAliases}) + let moduleAliases = toDictionary(relevantModules.compactMap { $0.moduleAliases }) let depProductModules = dependencyProductModules(of: relevantModules) var depProductAliases = [String: [String]]() - let depProductPrechainAliases = toDictionary(depProductModules.compactMap{$0.prechainModuleAliases}) + let depProductPrechainAliases = toDictionary(depProductModules.compactMap { $0.prechainModuleAliases }) for depProdModule in depProductModules { let depProdModuleAliases = depProdModule.moduleAliases ?? [:] @@ -234,7 +247,7 @@ struct ModuleAliasTracker { var shouldAddAliases = false if depProdModule.name == key { shouldAddAliases = true - } else if !depProductModules.map({$0.name}).contains(key) { + } else if !depProductModules.map({ $0.name }).contains(key) { shouldAddAliases = true } if shouldAddAliases { @@ -246,13 +259,15 @@ struct ModuleAliasTracker { } } } - chainModuleAliases(modules: curDirectModules, - checkedModules: relevantModules, - moduleAliases: moduleAliases, - childModules: depProductModules, - childAliases: depProductAliases, - childPrechainAliases: depProductPrechainAliases, - observabilityScope: observabilityScope) + chainModuleAliases( + modules: curDirectModules, + checkedModules: relevantModules, + moduleAliases: moduleAliases, + childModules: depProductModules, + childAliases: depProductAliases, + childPrechainAliases: depProductPrechainAliases, + observabilityScope: observabilityScope + ) } } @@ -266,7 +281,7 @@ struct ModuleAliasTracker { let unAliased = productModules.contains { $0.moduleAliases == nil } if unAliased { for module in productModules { - let depAliases = module.recursiveDependentModules.compactMap{$0.moduleAliases}.flatMap{$0} + let depAliases = module.recursiveDependentModules.compactMap { $0.moduleAliases }.flatMap { $0 } for (key, alias) in depAliases { appliedAliases.insert(key) module.addModuleAlias(for: key, as: alias) @@ -304,7 +319,7 @@ struct ModuleAliasTracker { var aliasDict = [String: String]() var prechainAliasDict = [String: [String]]() var directRefAliasDict = [String: [String]]() - let childDirectRefAliases = toDictionary(childModules.compactMap{$0.directRefAliases}) + let childDirectRefAliases = toDictionary(childModules.compactMap { $0.directRefAliases }) for (childModuleName, childModuleAliases) in childAliases { // Tracks whether to add prechain aliases to modules var addPrechainAliases = false @@ -323,7 +338,7 @@ struct ModuleAliasTracker { // name exist so they should not be applied; their aliases / new // names should be used directly addPrechainAliases = true - } else if childModules.filter({$0.name == childModuleName}).count > 1 { + } else if childModules.filter({ $0.name == childModuleName }).count > 1 { // Modules from different products have the same name as this child // module name, so their aliases should not be applied addPrechainAliases = true @@ -331,16 +346,16 @@ struct ModuleAliasTracker { if addPrechainAliases { if let prechainAliases = childPrechainAliases[childModuleName] { - for prechainAliasKey in prechainAliases { - if let prechainAliasVals = childPrechainAliases[prechainAliasKey] { - // If aliases are chained, keep track of prechain - // aliases - prechainAliasDict[prechainAliasKey, default: []].append(contentsOf: prechainAliasVals) - // Add prechained aliases to the list of aliases - // that should be directly referenced in source code - directRefAliasDict[childModuleName, default: []].append(prechainAliasKey) - directRefAliasDict[prechainAliasKey, default: []].append(contentsOf: prechainAliasVals) - } + for prechainAliasKey in prechainAliases { + if let prechainAliasVals = childPrechainAliases[prechainAliasKey] { + // If aliases are chained, keep track of prechain + // aliases + prechainAliasDict[prechainAliasKey, default: []].append(contentsOf: prechainAliasVals) + // Add prechained aliases to the list of aliases + // that should be directly referenced in source code + directRefAliasDict[childModuleName, default: []].append(prechainAliasKey) + directRefAliasDict[prechainAliasKey, default: []].append(contentsOf: prechainAliasVals) + } } } else if aliasDict[childModuleName] == nil { // If not added to aliasDict, use the renamed module directly @@ -352,7 +367,8 @@ struct ModuleAliasTracker { } // Check if not in child modules' direct ref aliases list, then add if lookupAlias(value: childModuleName, in: childDirectRefAliases).isEmpty, - childDirectRefAliases[childModuleName] == nil { + childDirectRefAliases[childModuleName] == nil + { aliasDict[childModuleName] = productModuleAlias } } @@ -365,7 +381,8 @@ struct ModuleAliasTracker { } for (key, valList) in prechainAliasDict { if let val = valList.first, - valList.count <= 1 { + valList.count <= 1 + { appliedAliases.insert(key) module.addModuleAlias(for: key, as: val) module.addPrechainModuleAlias(for: key, as: val) @@ -387,7 +404,7 @@ struct ModuleAliasTracker { } private func lookupAlias(value: String, in dict: [String: [String]]) -> [String] { - let keys = dict.filter{$0.value.contains(value)}.map{$0.key} + let keys = dict.filter { $0.value.contains(value) }.map { $0.key } return keys } @@ -416,7 +433,7 @@ struct ModuleAliasTracker { } private func dependencyProductModules(of modules: [Module]) -> [Module] { - let result = modules.map{$0.dependencies.compactMap{$0.product?.identity}}.flatMap{$0}.compactMap{productToAllModules[$0]}.flatMap{$0} + let result = modules.map { $0.dependencies.compactMap { $0.product?.identity } }.flatMap { $0 }.compactMap { productToAllModules[$0] }.flatMap { $0 } return result } } @@ -452,9 +469,9 @@ extension Module { var list = [Module]() var nextDeps = self.dependencies while !nextDeps.isEmpty { - let nextModules = nextDeps.compactMap{$0.module} + let nextModules = nextDeps.compactMap { $0.module } list.append(contentsOf: nextModules) - nextDeps = nextModules.map{$0.dependencies}.flatMap{$0} + nextDeps = nextModules.map { $0.dependencies }.flatMap { $0 } } return list } diff --git a/Sources/PackageGraph/ModulesGraph+Loading.swift b/Sources/PackageGraph/ModulesGraph+Loading.swift index 4576b28a65d..d70f60ed2a5 100644 --- a/Sources/PackageGraph/ModulesGraph+Loading.swift +++ b/Sources/PackageGraph/ModulesGraph+Loading.swift @@ -30,7 +30,7 @@ extension ModulesGraph { requiredDependencies: [PackageReference] = [], unsafeAllowedPackages: Set = [], binaryArtifacts: [PackageIdentity: [String: BinaryArtifact]], - prebuilts: [PackageIdentity: [String: PrebuiltLibrary]], // Product name to library mapping + prebuilts: [PackageIdentity: [String: PrebuiltLibrary]], // Product name to library mapping shouldCreateMultipleTestProducts: Bool = false, createREPLProduct: Bool = false, customPlatformsRegistry: PlatformRegistry? = .none, @@ -52,9 +52,11 @@ extension ModulesGraph { } // Construct the root dependencies set. - let rootDependencies = Set(root.dependencies.compactMap { - manifestMap[$0.identity]?.manifest - }) + let rootDependencies = Set( + root.dependencies.compactMap { + manifestMap[$0.identity]?.manifest + } + ) let rootManifestNodes = try root.packages.map { identity, package in // If we have enabled traits passed then we start with those. If there are no enabled @@ -87,10 +89,11 @@ extension ModulesGraph { let nodeSuccessorProvider = { (node: KeyedPair) in try (node.item.requiredDependencies + node.item.traitGuardedDependencies) - .compactMap { dependency -> KeyedPair< - GraphLoadingNode, - PackageIdentity - >? in + .compactMap { + dependency -> KeyedPair< + GraphLoadingNode, + PackageIdentity + >? in return try manifestMap[dependency.identity].map { manifest, _ in // We are going to check the conditionally enabled traits here and enable them if // required. This checks the current node and then enables the conditional @@ -113,9 +116,12 @@ extension ModulesGraph { if !root.manifests.allSatisfy({ $1.toolsVersion >= .v6_0 }) { if let cycle = try findCycle(inputManifests, successors: nodeSuccessorProvider) { let path = (cycle.path + cycle.cycle).map(\.item.manifest) - observabilityScope.emit(PackageGraphError.dependencyCycleDetected( - path: path, cycle: cycle.cycle[0].item.manifest - )) + observabilityScope.emit( + PackageGraphError.dependencyCycleDetected( + path: path, + cycle: cycle.cycle[0].item.manifest + ) + ) return try ModulesGraph( rootPackages: [], @@ -179,9 +185,9 @@ extension ModulesGraph { manifestToPackage[manifest] = package // Throw if any of the non-root package is empty. - if package.modules.isEmpty // System packages have modules in the package but not the manifest. + if package.modules.isEmpty // System packages have modules in the package but not the manifest. && package.manifest.targets - .isEmpty // An unneeded dependency will not have loaded anything from the manifest. + .isEmpty // An unneeded dependency will not have loaded anything from the manifest. && !manifest.packageKind.isRoot { throw PackageGraphError.noModules(package) @@ -189,11 +195,12 @@ extension ModulesGraph { } } - let platformVersionProvider: PlatformVersionProvider = if let customXCTestMinimumDeploymentTargets { - .init(implementation: .customXCTestMinimumDeploymentTargets(customXCTestMinimumDeploymentTargets)) - } else { - .init(implementation: .minimumDeploymentTargetDefault) - } + let platformVersionProvider: PlatformVersionProvider = + if let customXCTestMinimumDeploymentTargets { + .init(implementation: .customXCTestMinimumDeploymentTargets(customXCTestMinimumDeploymentTargets)) + } else { + .init(implementation: .minimumDeploymentTargetDefault) + } // Resolve dependencies and create resolved packages. let resolvedPackages = try createResolvedPackages( @@ -237,32 +244,36 @@ private func checkAllDependenciesAreUsed( ) { for package in rootPackages { // List all dependency products dependent on by the package modules. - let productDependencies = IdentifiableSet(package.modules.flatMap { module in - module.dependencies.compactMap { moduleDependency in - switch moduleDependency { - case .product(let product, _): - product - case .module: - nil + let productDependencies = IdentifiableSet( + package.modules.flatMap { module in + module.dependencies.compactMap { moduleDependency in + switch moduleDependency { + case .product(let product, _): + product + case .module: + nil + } } } - }) + ) // List all dependencies of modules that are guarded by a trait. - let traitGuardedProductDependencies = Set(package.underlying.modules.flatMap { module in - module.dependencies.compactMap { moduleDependency in - switch moduleDependency { - case .product(let product, let conditions): - if conditions.contains(where: { $0.traitCondition != nil }) { - // This is a product dependency that was enabled by a trait - return product.name + let traitGuardedProductDependencies = Set( + package.underlying.modules.flatMap { module in + module.dependencies.compactMap { moduleDependency in + switch moduleDependency { + case .product(let product, let conditions): + if conditions.contains(where: { $0.traitCondition != nil }) { + // This is a product dependency that was enabled by a trait + return product.name + } + return nil + case .module: + return nil } - return nil - case .module: - return nil } } - }) + ) for dependencyId in package.dependencies { guard let dependency = packages[dependencyId] else { @@ -346,13 +357,17 @@ private func findAllTransitiveDependencies( dependency: CanonicalPackageLocation, graph: [ResolvedPackageBuilder] ) throws -> [[CanonicalPackageLocation]] { - let edges = try Dictionary(uniqueKeysWithValues: graph.map { try ( - $0.package.manifest.canonicalPackageLocation, - Set( - $0.package.manifest.dependenciesRequired(for: $0.productFilter, $0.enabledTraits) - .map(\.packageRef.canonicalLocation) - ) - ) }) + let edges = try Dictionary( + uniqueKeysWithValues: graph.map { + try ( + $0.package.manifest.canonicalPackageLocation, + Set( + $0.package.manifest.dependenciesRequired(for: $0.productFilter, $0.enabledTraits) + .map(\.packageRef.canonicalLocation) + ) + ) + } + ) // Use BFS to find paths between start and finish. var queue: [(CanonicalPackageLocation, [CanonicalPackageLocation])] = [] var foundPaths: [[CanonicalPackageLocation]] = [] @@ -456,35 +471,32 @@ private func createResolvedPackages( // check if the resolved package location is the same as the dependency one // if not, this means that the dependencies share the same identity // which only allowed when overriding - if resolvedPackage.package.manifest.canonicalPackageLocation != dependencyPackageRef + if resolvedPackage.package.manifest.canonicalPackageLocation + != dependencyPackageRef .canonicalLocation && !resolvedPackage.allowedToOverride { let rootPackages = packageBuilders.filter { $0.allowedToOverride == true } - let dependenciesPaths = try rootPackages.map { try findAllTransitiveDependencies( - root: $0.package.manifest.canonicalPackageLocation, - dependency: dependencyPackageRef.canonicalLocation, - graph: packageBuilders - ) }.filter { !$0.isEmpty }.flatMap { $0 } - let otherDependenciesPaths = try rootPackages.map { try findAllTransitiveDependencies( - root: $0.package.manifest.canonicalPackageLocation, - dependency: resolvedPackage.package.manifest.canonicalPackageLocation, - graph: packageBuilders - ) }.filter { !$0.isEmpty }.flatMap { $0 } + let dependenciesPaths = try rootPackages.map { + try findAllTransitiveDependencies( + root: $0.package.manifest.canonicalPackageLocation, + dependency: dependencyPackageRef.canonicalLocation, + graph: packageBuilders + ) + }.filter { !$0.isEmpty }.flatMap { $0 } + let otherDependenciesPaths = try rootPackages.map { + try findAllTransitiveDependencies( + root: $0.package.manifest.canonicalPackageLocation, + dependency: resolvedPackage.package.manifest.canonicalPackageLocation, + graph: packageBuilders + ) + }.filter { !$0.isEmpty }.flatMap { $0 } packageObservabilityScope .emit( - debug: ( - "Conflicting identity for \(dependency.identity): " + - "chains of dependencies for \(dependencyPackageRef.locationString): " + - "\(String(describing: dependenciesPaths))" - ) + debug: ("Conflicting identity for \(dependency.identity): " + "chains of dependencies for \(dependencyPackageRef.locationString): " + "\(String(describing: dependenciesPaths))") ) packageObservabilityScope .emit( - debug: ( - "Conflicting identity for \(dependency.identity): " + - "chains of dependencies for \(resolvedPackage.package.manifest.packageLocation): " + - "\(String(describing: otherDependenciesPaths))" - ) + debug: ("Conflicting identity for \(dependency.identity): " + "chains of dependencies for \(resolvedPackage.package.manifest.packageLocation): " + "\(String(describing: otherDependenciesPaths))") ) let error = PackageGraphError.dependencyAlreadySatisfiedByIdentifier( package: package.identity.description, @@ -497,9 +509,10 @@ private func createResolvedPackages( // 9/2021 this is currently emitting a warning only to support // backwards compatibility with older versions of SwiftPM that had too weak of a validation // we will upgrade this to an error in a few versions to tighten up the validation - if dependency.explicitNameForModuleDependencyResolutionOnly == .none || - resolvedPackage.package.manifest.displayName == dependency - .explicitNameForModuleDependencyResolutionOnly + if dependency.explicitNameForModuleDependencyResolutionOnly == .none + || resolvedPackage.package.manifest.displayName + == dependency + .explicitNameForModuleDependencyResolutionOnly { packageObservabilityScope .emit( @@ -509,10 +522,9 @@ private func createResolvedPackages( } else { return packageObservabilityScope.emit(error) } - } else if resolvedPackage.package.manifest.canonicalPackageLocation == dependencyPackageRef - .canonicalLocation && - resolvedPackage.package.manifest.packageLocation != dependencyPackageRef.locationString && - !resolvedPackage.allowedToOverride + } else if resolvedPackage.package.manifest.canonicalPackageLocation + == dependencyPackageRef + .canonicalLocation && resolvedPackage.package.manifest.packageLocation != dependencyPackageRef.locationString && !resolvedPackage.allowedToOverride { packageObservabilityScope .emit( @@ -550,7 +562,8 @@ private func createResolvedPackages( return packageObservabilityScope.emit(error) } - let nameForModuleDependencyResolution = dependency + let nameForModuleDependencyResolution = + dependency .explicitNameForModuleDependencyResolutionOnly ?? dependency.identity.description dependenciesByNameForModuleDependencyResolution[nameForModuleDependencyResolution] = resolvedPackage dependencyNamesForModuleDependencyResolutionOnly[resolvedPackage.package.identity] = @@ -572,11 +585,12 @@ private func createResolvedPackages( ) // Create module builders for each module in the package. - let modules: [Module] = if let modulesFilter { - package.modules.filter(modulesFilter) - } else { - package.modules - } + let modules: [Module] = + if let modulesFilter { + package.modules.filter(modulesFilter) + } else { + package.modules + } let moduleBuilders = modules.map { ResolvedModuleBuilder( packageIdentity: package.identity, @@ -609,11 +623,12 @@ private func createResolvedPackages( // Create product builders for each product in the package. A product can only contain a module present in the // same package. - let products: [Product] = if let productsFilter { - package.products.filter(productsFilter) - } else { - package.products - } + let products: [Product] = + if let productsFilter { + package.products.filter(productsFilter) + } else { + package.products + } packageBuilder.products = try products.map { product in try ResolvedProductBuilder( @@ -677,8 +692,7 @@ private func createResolvedPackages( } let packageDoesNotSupportProductAliases = packageBuilder.package.doesNotSupportProductAliases - let lookupByProductIDs = !packageDoesNotSupportProductAliases && - (packageBuilder.package.manifest.disambiguateByProductIDs || moduleAliasingUsed) + let lookupByProductIDs = !packageDoesNotSupportProductAliases && (packageBuilder.package.manifest.disambiguateByProductIDs || moduleAliasingUsed) // Get all the products from dependencies of this package. let productDependencies = packageBuilder.dependencies @@ -690,37 +704,44 @@ private func createResolvedPackages( let explicitIdsOrNames = Set(explicitProducts.lazy.map { lookupByProductIDs ? $0.identity : $0.name }) return dependency.products .filter { - lookupByProductIDs ? explicitIdsOrNames.contains($0.product.identity) : explicitIdsOrNames - .contains($0.product.name) + lookupByProductIDs + ? explicitIdsOrNames.contains($0.product.identity) + : explicitIdsOrNames + .contains($0.product.name) } } - let productDependencyMap: [String: ResolvedProductBuilder] = if lookupByProductIDs { - try Dictionary(uniqueKeysWithValues: productDependencies.map { - guard let packageName = packageBuilder - .dependencyNamesForModuleDependencyResolutionOnly[$0.packageBuilder.package.identity] - else { - throw InternalError( - "could not determine name for dependency on package '\($0.packageBuilder.package.identity)' from package '\(packageBuilder.package.identity)'" - ) - } - let key = "\(packageName.lowercased())_\($0.product.name)" - return (key, $0) - }) - } else { - try Dictionary( - productDependencies.map { ($0.product.name, $0) }, - uniquingKeysWith: { lhs, _ in - let duplicates = productDependencies.filter { $0.product.name == lhs.product.name } - throw emitDuplicateProductDiagnostic( - productName: lhs.product.name, - packages: duplicates.map(\.packageBuilder.package), - moduleAliasingUsed: moduleAliasingUsed, - observabilityScope: observabilityScope - ) - } - ) - } + let productDependencyMap: [String: ResolvedProductBuilder] = + if lookupByProductIDs { + try Dictionary( + uniqueKeysWithValues: productDependencies.map { + guard + let packageName = + packageBuilder + .dependencyNamesForModuleDependencyResolutionOnly[$0.packageBuilder.package.identity] + else { + throw InternalError( + "could not determine name for dependency on package '\($0.packageBuilder.package.identity)' from package '\(packageBuilder.package.identity)'" + ) + } + let key = "\(packageName.lowercased())_\($0.product.name)" + return (key, $0) + } + ) + } else { + try Dictionary( + productDependencies.map { ($0.product.name, $0) }, + uniquingKeysWith: { lhs, _ in + let duplicates = productDependencies.filter { $0.product.name == lhs.product.name } + throw emitDuplicateProductDiagnostic( + productName: lhs.product.name, + packages: duplicates.map(\.packageBuilder.package), + moduleAliasingUsed: moduleAliasingUsed, + observabilityScope: observabilityScope + ) + } + ) + } // Establish dependencies in each module. for moduleBuilder in packageBuilder.modules { @@ -749,8 +770,7 @@ private func createResolvedPackages( // Find the product in this package's dependency products. // Look it up by ID if module aliasing is used, otherwise by name. - let product = lookupByProductIDs ? productDependencyMap[productRef.identity] : - productDependencyMap[productRef.name] + let product = lookupByProductIDs ? productDependencyMap[productRef.identity] : productDependencyMap[productRef.name] guard let product else { // Only emit a diagnostic if there are no other diagnostics. // This avoids flooding the diagnostics with product not @@ -774,12 +794,13 @@ private func createResolvedPackages( // we can provide a more detailed diagnostic here. if packageBuilder.package.manifest.toolsVersion >= .v5_2 && productRef.package == nil { let referencedPackageIdentity = product.packageBuilder.package.identity - guard let referencedPackageDependency = ( - packageBuilder.package.manifest.dependencies - .first { package in - package.identity == referencedPackageIdentity - } - ) else { + guard + let referencedPackageDependency = + (packageBuilder.package.manifest.dependencies + .first { package in + package.identity == referencedPackageIdentity + }) + else { throw InternalError( "dependency reference for \(product.packageBuilder.package.manifest.packageLocation) not found" ) @@ -804,7 +825,8 @@ private func createResolvedPackages( if foundDuplicateModule { var duplicateModules = [String: [Package]]() for moduleName in Set(allModuleNames).sorted() { - let packages = packageBuilders + let packages = + packageBuilders .filter { $0.modules.contains(where: { $0.module.name == moduleName }) } .map(\.package) if packages.count > 1 { @@ -824,14 +846,13 @@ private func createResolvedPackages( var duplicateModulesAddressed = [String]() for potentiallyDuplicatePackage in potentiallyDuplicatePackages { // more than three module matches, or all modules in the package match - if potentiallyDuplicatePackage.value.count > 3 || - ( - potentiallyDuplicatePackage.value.sorted() == potentiallyDuplicatePackage.key.package1.modules - .map(\.name).sorted() - && - potentiallyDuplicatePackage.value.sorted() == potentiallyDuplicatePackage.key.package2.modules - .map(\.name).sorted() - ) + if potentiallyDuplicatePackage.value.count > 3 + || (potentiallyDuplicatePackage.value.sorted() + == potentiallyDuplicatePackage.key.package1.modules + .map(\.name).sorted() + && potentiallyDuplicatePackage.value.sorted() + == potentiallyDuplicatePackage.key.package2.modules + .map(\.name).sorted()) { switch ( potentiallyDuplicatePackage.key.package1.identity.registry, @@ -882,16 +903,19 @@ private func createResolvedPackages( KeyedPair($0, key: $0.module) } } - if let cycle = findCycle(moduleBuilders, successors: { - $0.item.dependencies.flatMap { - switch $0 { - case .product(let productBuilder, conditions: _): - return productBuilder.moduleBuilders.map { KeyedPair($0, key: $0.module) } - case .module: - return [] // local modules were checked by PackageBuilder. + if let cycle = findCycle( + moduleBuilders, + successors: { + $0.item.dependencies.flatMap { + switch $0 { + case .product(let productBuilder, conditions: _): + return productBuilder.moduleBuilders.map { KeyedPair($0, key: $0.module) } + case .module: + return [] // local modules were checked by PackageBuilder. + } } } - }) { + ) { observabilityScope.emit( ModuleError.cycleDetected( (cycle.path.map(\.key.name), cycle.cycle.map(\.key.name)) @@ -961,10 +985,11 @@ private func prepareProductDependencyNotFoundError( // is already a part of the dependency tree. let availableProducts = Dictionary( uniqueKeysWithValues: packageBuilder.dependencies - .flatMap { (packageDep: ResolvedPackageBuilder) -> [( - String, - String - )] in + .flatMap { + (packageDep: ResolvedPackageBuilder) -> [( + String, + String + )] in let manifestProducts = packageDep.package.manifest.products.map(\.name) let explicitProducts = packageDep.package.products.filter { manifestProducts.contains($0.name) } let explicitIdsOrNames = Set(explicitProducts.map { lookupByProductIDs ? $0.identity : $0.name }) @@ -1094,8 +1119,7 @@ private struct Pair: Hashable { let package2: Package static func == (lhs: Pair, rhs: Pair) -> Bool { - lhs.package1.identity == rhs.package1.identity && - lhs.package2.identity == rhs.package2.identity + lhs.package1.identity == rhs.package1.identity && lhs.package2.identity == rhs.package2.identity } public func hash(into hasher: inout Hasher) { @@ -1136,7 +1160,8 @@ private class DuplicateProductsChecker { if !self.checkedPkgIDs.contains(depPkg) { self.checkedPkgIDs.append(depPkg) } - let depProductIDs = self.packageIDToBuilder[depPkg]?.package.products + let depProductIDs = + self.packageIDToBuilder[depPkg]?.package.products .filter { $0.identity == depRef.identity } .map { useProductIDs && $0.isDefaultLibrary ? $0.identity : $0.name } ?? [] for depID in depProductIDs { @@ -1144,7 +1169,7 @@ private class DuplicateProductsChecker { } } else { let depPkgs = pkgBuilder.dependencies - .filter { $0.products.contains { $0.product.name == depRef.name }}.map(\.package.identity) + .filter { $0.products.contains { $0.product.name == depRef.name } }.map(\.package.identity) productToPkgMap[depRef.name, default: .init()].formUnion(Set(depPkgs)) self.checkedPkgIDs.append(contentsOf: depPkgs) } @@ -1198,7 +1223,8 @@ private func computePlatforms( ) -> [SupportedPlatform] { // the supported platforms as declared in the manifest let declaredPlatforms: [SupportedPlatform] = package.manifest.platforms.map { platform in - let declaredPlatform = platformRegistry.platformByName[platform.platformName] + let declaredPlatform = + platformRegistry.platformByName[platform.platformName] ?? PackageModel.Platform.custom(name: platform.platformName, oldestSupportedVersion: platform.version) return SupportedPlatform( platform: declaredPlatform, @@ -1216,15 +1242,16 @@ private func resolveModuleAliases( observabilityScope: ObservabilityScope ) throws -> Bool { // If there are no module aliases specified, return early - let hasAliases = packageBuilders.contains { $0.package.modules.contains { - $0.dependencies.contains { dep in - if case .product(let prodRef, _) = dep { - return prodRef.moduleAliases != nil + let hasAliases = packageBuilders.contains { + $0.package.modules.contains { + $0.dependencies.contains { dep in + if case .product(let prodRef, _) = dep { + return prodRef.moduleAliases != nil + } + return false } - return false } } - } guard hasAliases else { return false } var aliasTracker = ModuleAliasTracker() diff --git a/Sources/PackageGraph/ModulesGraph.swift b/Sources/PackageGraph/ModulesGraph.swift index 5df55390e6f..abf55bfc708 100644 --- a/Sources/PackageGraph/ModulesGraph.swift +++ b/Sources/PackageGraph/ModulesGraph.swift @@ -87,7 +87,8 @@ enum PackageGraphError: Swift.Error { ) } -@available(*, +@available( + *, deprecated, renamed: "ModulesGraph", message: "PackageGraph had a misleading name, it's a graph of dependencies between modules, not just packages" @@ -134,9 +135,10 @@ public struct ModulesGraph { ) { (accumulator: inout IdentifiableSet, package: ResolvedPackage) in let allDependencies = package.modules.flatMap { $0.dependencies } let unsatisfiedDependencies = allDependencies.filter { !$0.satisfies(buildEnvironment) } - let unsatisfiedDependencyModules = unsatisfiedDependencies.compactMap { ( - dep: ResolvedModule.Dependency - ) -> ResolvedModule? in + let unsatisfiedDependencyModules = unsatisfiedDependencies.compactMap { + ( + dep: ResolvedModule.Dependency + ) -> ResolvedModule? in switch dep { case .module(let moduleDependency, _): return moduleDependency @@ -214,13 +216,14 @@ public struct ModulesGraph { var allModules = IdentifiableSet() var allProducts = IdentifiableSet() for package in self.packages { - let modulesToInclude = if rootPackages.contains(id: package.id) { - Array(package.modules) - } else { - // Don't include tests modules from non-root packages so swift-test doesn't - // try to run them. - package.modules.filter { $0.type != .test } - } + let modulesToInclude = + if rootPackages.contains(id: package.id) { + Array(package.modules) + } else { + // Don't include tests modules from non-root packages so swift-test doesn't + // try to run them. + package.modules.filter { $0.type != .test } + } for module in modulesToInclude { allModules.insert(module) @@ -270,9 +273,12 @@ public struct ModulesGraph { for module in rootModules where module.type == .executable { // Find all dependencies of this module within its package. Note that we do not traverse plugin usages. - let dependencies = try topologicalSortIdentifiable(module.dependencies, successors: { - $0.dependencies.compactMap{ $0.module }.filter{ $0.type != .plugin }.map{ .module($0, conditions: []) } - }).compactMap({ $0.module }) + let dependencies = try topologicalSortIdentifiable( + module.dependencies, + successors: { + $0.dependencies.compactMap { $0.module }.filter { $0.type != .plugin }.map { .module($0, conditions: []) } + } + ).compactMap({ $0.module }) // Include the test modules whose dependencies intersect with the // current module's (recursive) dependencies. @@ -290,8 +296,7 @@ public struct ModulesGraph { if self.rootPackages.isEmpty { throw StringError("Root package does not exist.") } - return self.rootPackages[self.rootPackages.startIndex].identity.description + - Product.replProductSuffix + return self.rootPackages[self.rootPackages.startIndex].identity.description + Product.replProductSuffix } } @@ -302,9 +307,7 @@ extension PackageGraphError: CustomStringConvertible { return "package '\(package)' contains no products" case .dependencyCycleDetected(let path, let package): - return "cyclic dependency between packages " + - (path.map({ $0.displayName }).joined(separator: " -> ")) + - " -> \(package.displayName) requires tools-version 6.0 or later" + return "cyclic dependency between packages " + (path.map({ $0.displayName }).joined(separator: " -> ")) + " -> \(package.displayName) requires tools-version 6.0 or later" case .productDependencyNotFound(let package, let moduleName, let dependencyProductName, let dependencyPackageName, let dependencyProductInDecl, let similarProductName, let packageContainingSimilarProduct): if dependencyProductInDecl { @@ -327,19 +330,11 @@ extension PackageGraphError: CustomStringConvertible { let otherDependencyPath ): var description = - "Conflicting identity for \(identity): " + - "dependency '\(dependencyURL)' and dependency '\(otherDependencyURL)' " + - "both point to the same package identity '\(identity)'." + "Conflicting identity for \(identity): " + "dependency '\(dependencyURL)' and dependency '\(otherDependencyURL)' " + "both point to the same package identity '\(identity)'." if !dependencyPath.isEmpty && !otherDependencyPath.isEmpty { let chainA = dependencyPath.map { String(describing: $0) }.joined(separator: "->") let chainB = otherDependencyPath.map { String(describing: $0) }.joined(separator: "->") - description += ( - " The dependencies are introduced through the following chains: " + - "(A) \(chainA) (B) \(chainB). If there are multiple chains that lead to the same dependency, " + - "only the first chain is shown here. To see all chains use debug output option. " + - "To resolve the conflict, coordinate with the maintainer of the package " + - "that introduces the conflicting dependency." - ) + description += (" The dependencies are introduced through the following chains: " + "(A) \(chainA) (B) \(chainB). If there are multiple chains that lead to the same dependency, " + "only the first chain is shown here. To see all chains use debug output option. " + "To resolve the conflict, coordinate with the maintainer of the package " + "that introduces the conflicting dependency.") } return description @@ -353,9 +348,9 @@ extension PackageGraphError: CustomStringConvertible { ): let solution = """ - reference the package in the target dependency with '.product(name: "\(productName)", package: \ - "\(packageIdentifier)")' - """ + reference the package in the target dependency with '.product(name: "\(productName)", package: \ + "\(packageIdentifier)")' + """ return "dependency '\(productName)' in target '\(moduleName)' requires explicit declaration; \(solution)" @@ -364,8 +359,8 @@ extension PackageGraphError: CustomStringConvertible { var description = "'\($0.identity)'" switch $0.manifest.packageKind { case .root(let path), - .fileSystem(let path), - .localSourceControl(let path): + .fileSystem(let path), + .localSourceControl(let path): description += " (at '\(path)')" case .remoteSourceControl(let url): description += " (from '\(url)')" @@ -377,10 +372,10 @@ extension PackageGraphError: CustomStringConvertible { return "multiple packages (\(packagesDescriptions.joined(separator: ", "))) declare products with a conflicting name: '\(product)’; product names need to be unique across the package graph" case .multipleModuleAliases(let target, let product, let package, let aliases): return "multiple aliases: ['\(aliases.joined(separator: "', '"))'] found for target '\(target)' in product '\(product)' from package '\(package)'" - case .unsupportedPluginDependency(let targetName, let dependencyName, let dependencyType, let dependencyPackage): + case .unsupportedPluginDependency(let targetName, let dependencyName, let dependencyType, let dependencyPackage): var trailingMsg = "" if let dependencyPackage { - trailingMsg = " from package '\(dependencyPackage)'" + trailingMsg = " from package '\(dependencyPackage)'" } return "plugin '\(targetName)' cannot depend on '\(dependencyName)' of type '\(dependencyType)'\(trailingMsg); this dependency is unsupported" } @@ -410,12 +405,17 @@ enum GraphError: Error { /// - Complexity: O(v + e) where (v, e) are the number of vertices and edges /// reachable from the input nodes via the relation. func topologicalSortIdentifiable( - _ nodes: [T], successors: (T) throws -> [T] + _ nodes: [T], + successors: (T) throws -> [T] ) throws -> [T] { // Implements a topological sort via recursion and reverse postorder DFS. - func visit(_ node: T, - _ stack: inout OrderedCollections.OrderedSet, _ visited: inout Set, _ result: inout [T], - _ successors: (T) throws -> [T]) throws { + func visit( + _ node: T, + _ stack: inout OrderedCollections.OrderedSet, + _ visited: inout Set, + _ result: inout [T], + _ successors: (T) throws -> [T] + ) throws { // Mark this node as visited -- we are done if it already was. if !visited.insert(node.id).inserted { return @@ -492,8 +492,10 @@ public func loadModulesGraph( return try ModulesGraph.load( root: graphRoot, identityResolver: identityResolver, - additionalFileRules: useXCBuildFileRules ? FileRuleDescription.xcbuildFileTypes : FileRuleDescription - .swiftpmFileTypes, + additionalFileRules: useXCBuildFileRules + ? FileRuleDescription.xcbuildFileTypes + : FileRuleDescription + .swiftpmFileTypes, externalManifests: externalManifests, binaryArtifacts: binaryArtifacts, prebuilts: prebuilts, diff --git a/Sources/PackageGraph/PackageContainer.swift b/Sources/PackageGraph/PackageContainer.swift index f1029ad3d5f..54f0c8da038 100644 --- a/Sources/PackageGraph/PackageContainer.swift +++ b/Sources/PackageGraph/PackageContainer.swift @@ -120,9 +120,9 @@ extension PackageContainer { public protocol CustomPackageContainer: PackageContainer { /// Retrieve the package using this package container. func retrieve( - at version: Version, - progressHandler: ((_ bytesReceived: Int64, _ totalBytes: Int64?) -> Void)?, - observabilityScope: ObservabilityScope + at version: Version, + progressHandler: ((_ bytesReceived: Int64, _ totalBytes: Int64?) -> Void)?, + observabilityScope: ObservabilityScope ) throws -> AbsolutePath /// Get the custom file system for this package container. diff --git a/Sources/PackageGraph/PackageGraphRoot.swift b/Sources/PackageGraph/PackageGraphRoot.swift index e99ccd9d332..8697bde9915 100644 --- a/Sources/PackageGraph/PackageGraphRoot.swift +++ b/Sources/PackageGraph/PackageGraphRoot.swift @@ -94,13 +94,16 @@ public struct PackageGraphRoot { observabilityScope: ObservabilityScope, enabledTraitsMap: EnabledTraitsMap = .init() ) throws { - self.packages = input.packages.reduce(into: .init(), { partial, inputPath in - if let manifest = manifests[inputPath] { - let packagePath = manifest.path.parentDirectory - let identity = PackageIdentity(path: packagePath) // this does not use the identity resolver which is fine since these are the root packages - partial[identity] = (.root(identity: identity, path: packagePath), manifest) + self.packages = input.packages.reduce( + into: .init(), + { partial, inputPath in + if let manifest = manifests[inputPath] { + let packagePath = manifest.path.parentDirectory + let identity = PackageIdentity(path: packagePath) // this does not use the identity resolver which is fine since these are the root packages + partial[identity] = (.root(identity: identity, path: packagePath), manifest) + } } - }) + ) // FIXME: Deprecate special casing once the manifest supports declaring used executable products. // Special casing explicit products like this is necessary to pass the test suite and satisfy backwards compatibility. @@ -156,8 +159,9 @@ public struct PackageGraphRoot { enabledTraits: enabledTraits ) } - - let depend = try dependencies + + let depend = + try dependencies .map { dep in let enabledTraits = dep.traits?.filter { guard let condition = $0.condition else { return true } @@ -173,7 +177,7 @@ public struct PackageGraphRoot { products: dep.productFilter, enabledTraits: enabledTraitsSet ) - } + } return constraints + depend } @@ -220,4 +224,3 @@ extension PackageDependency.Registry.Requirement { } } } - diff --git a/Sources/PackageGraph/PackageModel+Extensions.swift b/Sources/PackageGraph/PackageModel+Extensions.swift index 6c4084e49e0..3b231097036 100644 --- a/Sources/PackageGraph/PackageModel+Extensions.swift +++ b/Sources/PackageGraph/PackageModel+Extensions.swift @@ -67,7 +67,7 @@ extension PackageContainerConstraint { assertionFailure("Attempted to enumerate a root package’s product filter; root packages have no filter.") return [] case .specific(let set): - if set.isEmpty { // Pointing at the package without a particular product. + if set.isEmpty { // Pointing at the package without a particular product. return [.empty(package: self.package)] } else { return set.sorted().map { .product($0, package: self.package, enabledTraits: self.enabledTraits) } diff --git a/Sources/PackageGraph/Resolution/DependencyResolutionNode.swift b/Sources/PackageGraph/Resolution/DependencyResolutionNode.swift index 5c71a8abd30..737fc7e20cd 100644 --- a/Sources/PackageGraph/Resolution/DependencyResolutionNode.swift +++ b/Sources/PackageGraph/Resolution/DependencyResolutionNode.swift @@ -130,7 +130,7 @@ public enum DependencyResolutionNode { } extension DependencyResolutionNode: Equatable { - public static func ==(lhs: DependencyResolutionNode, rhs: DependencyResolutionNode) -> Bool { + public static func == (lhs: DependencyResolutionNode, rhs: DependencyResolutionNode) -> Bool { return (lhs.package, lhs.specificProduct) == (rhs.package, rhs.specificProduct) } } diff --git a/Sources/PackageGraph/Resolution/DependencyResolverDelegate.swift b/Sources/PackageGraph/Resolution/DependencyResolverDelegate.swift index d570deb2711..736b5596621 100644 --- a/Sources/PackageGraph/Resolution/DependencyResolverDelegate.swift +++ b/Sources/PackageGraph/Resolution/DependencyResolverDelegate.swift @@ -31,7 +31,7 @@ public protocol DependencyResolverDelegate { public struct ObservabilityDependencyResolverDelegate: DependencyResolverDelegate { private let observabilityScope: ObservabilityScope - public init (observabilityScope: ObservabilityScope) { + public init(observabilityScope: ObservabilityScope) { self.observabilityScope = observabilityScope.makeChildScope(description: "DependencyResolver") } @@ -78,40 +78,40 @@ public struct ObservabilityDependencyResolverDelegate: DependencyResolverDelegat public struct MultiplexResolverDelegate: DependencyResolverDelegate { private let underlying: [DependencyResolverDelegate] - public init (_ underlying: [DependencyResolverDelegate]) { + public init(_ underlying: [DependencyResolverDelegate]) { self.underlying = underlying } public func willResolve(term: Term) { - underlying.forEach { $0.willResolve(term: term) } + underlying.forEach { $0.willResolve(term: term) } } public func didResolve(term: Term, version: Version, duration: DispatchTimeInterval) { - underlying.forEach { $0.didResolve(term: term, version: version, duration: duration) } + underlying.forEach { $0.didResolve(term: term, version: version, duration: duration) } } public func derived(term: Term) { - underlying.forEach { $0.derived(term: term) } + underlying.forEach { $0.derived(term: term) } } public func conflict(conflict: Incompatibility) { - underlying.forEach { $0.conflict(conflict: conflict) } + underlying.forEach { $0.conflict(conflict: conflict) } } public func satisfied(term: Term, by assignment: Assignment, incompatibility: Incompatibility) { - underlying.forEach { $0.satisfied(term: term, by: assignment, incompatibility: incompatibility) } + underlying.forEach { $0.satisfied(term: term, by: assignment, incompatibility: incompatibility) } } public func partiallySatisfied(term: Term, by assignment: Assignment, incompatibility: Incompatibility, difference: Term) { - underlying.forEach { $0.partiallySatisfied(term: term, by: assignment, incompatibility: incompatibility, difference: difference) } + underlying.forEach { $0.partiallySatisfied(term: term, by: assignment, incompatibility: incompatibility, difference: difference) } } public func failedToResolve(incompatibility: Incompatibility) { - underlying.forEach { $0.failedToResolve(incompatibility: incompatibility) } + underlying.forEach { $0.failedToResolve(incompatibility: incompatibility) } } public func solved(result: [DependencyResolverBinding]) { - underlying.forEach { $0.solved(result: result) } + underlying.forEach { $0.solved(result: result) } } } diff --git a/Sources/PackageGraph/Resolution/DependencyResolverError.swift b/Sources/PackageGraph/Resolution/DependencyResolverError.swift index 153031c41d4..6cfd6114430 100644 --- a/Sources/PackageGraph/Resolution/DependencyResolverError.swift +++ b/Sources/PackageGraph/Resolution/DependencyResolverError.swift @@ -13,7 +13,7 @@ import Foundation public enum DependencyResolverError: Error, Equatable { - /// A revision-based dependency contains a local package dependency. + /// A revision-based dependency contains a local package dependency. case revisionDependencyContainsLocalPackage(dependency: String, localPackage: String) } diff --git a/Sources/PackageGraph/Resolution/PlatformVersionProvider.swift b/Sources/PackageGraph/Resolution/PlatformVersionProvider.swift index 266523d6568..a0e35658d01 100644 --- a/Sources/PackageGraph/Resolution/PlatformVersionProvider.swift +++ b/Sources/PackageGraph/Resolution/PlatformVersionProvider.swift @@ -69,8 +69,8 @@ public struct PlatformVersionProvider: Hashable { var version = declaredPlatform.version if usingXCTest, - let xcTestMinimumDeploymentTarget = self.derivedXCTestPlatformProvider(platform), - version < xcTestMinimumDeploymentTarget + let xcTestMinimumDeploymentTarget = self.derivedXCTestPlatformProvider(platform), + version < xcTestMinimumDeploymentTarget { version = xcTestMinimumDeploymentTarget } @@ -88,8 +88,8 @@ public struct PlatformVersionProvider: Hashable { } else { let minimumSupportedVersion: PlatformVersion if usingXCTest, - let xcTestMinimumDeploymentTarget = self.derivedXCTestPlatformProvider(platform), - xcTestMinimumDeploymentTarget > platform.oldestSupportedVersion + let xcTestMinimumDeploymentTarget = self.derivedXCTestPlatformProvider(platform), + xcTestMinimumDeploymentTarget > platform.oldestSupportedVersion { minimumSupportedVersion = xcTestMinimumDeploymentTarget } else { diff --git a/Sources/PackageGraph/Resolution/PubGrub/ContainerProvider.swift b/Sources/PackageGraph/Resolution/PubGrub/ContainerProvider.swift index 6508e5e145d..fb887e5befe 100644 --- a/Sources/PackageGraph/Resolution/PubGrub/ContainerProvider.swift +++ b/Sources/PackageGraph/Resolution/PubGrub/ContainerProvider.swift @@ -83,7 +83,7 @@ final class ContainerProvider { // Otherwise, fetch the container from the provider self.underlying.getContainer( for: package, - updateStrategy: self.skipUpdate ? .never : .always, // TODO: make this more elaborate + updateStrategy: self.skipUpdate ? .never : .always, // TODO: make this more elaborate observabilityScope: self.observabilityScope.makeChildScope(description: "getting package container", metadata: package.diagnosticsMetadata), on: .sharedConcurrent ) { result in @@ -112,7 +112,7 @@ final class ContainerProvider { if needsFetching { self.underlying.getContainer( for: identifier, - updateStrategy: self.skipUpdate ? .never : .always, // TODO: make this more elaborate + updateStrategy: self.skipUpdate ? .never : .always, // TODO: make this more elaborate observabilityScope: self.observabilityScope.makeChildScope(description: "prefetching package container", metadata: identifier.diagnosticsMetadata), on: .sharedConcurrent ) { result in diff --git a/Sources/PackageGraph/Resolution/PubGrub/DiagnosticReportBuilder.swift b/Sources/PackageGraph/Resolution/PubGrub/DiagnosticReportBuilder.swift index c1b6275dcee..e89b5eb6086 100644 --- a/Sources/PackageGraph/Resolution/PubGrub/DiagnosticReportBuilder.swift +++ b/Sources/PackageGraph/Resolution/PubGrub/DiagnosticReportBuilder.swift @@ -158,8 +158,11 @@ struct DiagnosticReportBuilder { return } - let collapsedDerived = derivedCause.conflict.cause.isConflict ? derivedCause.conflict : derivedCause - .other + let collapsedDerived = + derivedCause.conflict.cause.isConflict + ? derivedCause.conflict + : derivedCause + .other let collapsedExt = derivedCause.conflict.cause.isConflict ? derivedCause.other : derivedCause.conflict try await self.visit(collapsedDerived) @@ -228,10 +231,13 @@ struct DiagnosticReportBuilder { let terms = incompatibility.terms if terms.count == 1 { let term = terms.first! - let prefix = try await hasEffectivelyAnyRequirement(term) ? term.node.nameForDiagnostics : self.description( - for: term, - normalizeRange: true - ) + let prefix = + try await hasEffectivelyAnyRequirement(term) + ? term.node.nameForDiagnostics + : self.description( + for: term, + normalizeRange: true + ) return "\(prefix) " + (term.isPositive ? "cannot be used" : "is required") } else if terms.count == 2 { let term1 = terms.first! @@ -338,12 +344,14 @@ struct DiagnosticReportBuilder { return "\(name) < \(range.upperBound)" } case .ranges(let ranges): - let ranges = "{" + ranges.map { - if $0.lowerBound == $0.upperBound { - return $0.lowerBound.description - } - return $0.lowerBound.description + "..<" + $0.upperBound.description - }.joined(separator: ", ") + "}" + let ranges = + "{" + + ranges.map { + if $0.lowerBound == $0.upperBound { + return $0.lowerBound.description + } + return $0.lowerBound.description + "..<" + $0.upperBound.description + }.joined(separator: ", ") + "}" return "\(name) \(ranges)" } } diff --git a/Sources/PackageGraph/Resolution/PubGrub/Incompatibility.swift b/Sources/PackageGraph/Resolution/PubGrub/Incompatibility.swift index 91bb4128552..8ab13a3b51f 100644 --- a/Sources/PackageGraph/Resolution/PubGrub/Incompatibility.swift +++ b/Sources/PackageGraph/Resolution/PubGrub/Incompatibility.swift @@ -41,7 +41,7 @@ public struct Incompatibility: Equatable, Hashable { // always be selected. var terms = terms if terms.count > 1, cause.isConflict, - terms.contains(where: { $0.isPositive && $0.node == root }) + terms.contains(where: { $0.isPositive && $0.node == root }) { terms = OrderedSet(terms.filter { !$0.isPositive || $0.node != root }) } @@ -141,7 +141,8 @@ extension Incompatibility { /// requirements to a^1.5.0. private func normalize(terms: [Term]) throws -> [Term] { let dict = try terms.reduce(into: OrderedCollections.OrderedDictionary()) { - res, term in + res, + term in // Don't try to intersect if this is the first time we're seeing this package. guard let previous = res[term.node] else { res[term.node] = (term.requirement, term.isPositive) @@ -149,12 +150,14 @@ private func normalize(terms: [Term]) throws -> [Term] { } guard let intersection = term.intersect(withRequirement: previous.req, andPolarity: previous.polarity) else { - throw InternalError(""" - Attempting to create an incompatibility with terms for \(term.node) \ - intersecting versions \(previous) and \(term.requirement). These are \ - mutually exclusive and can't be intersected, making this incompatibility \ - irrelevant. - """) + throw InternalError( + """ + Attempting to create an incompatibility with terms for \(term.node) \ + intersecting versions \(previous) and \(term.requirement). These are \ + mutually exclusive and can't be intersected, making this incompatibility \ + irrelevant. + """ + ) } res[term.node] = (intersection.requirement, intersection.isPositive) } diff --git a/Sources/PackageGraph/Resolution/PubGrub/PubGrubDependencyResolver.swift b/Sources/PackageGraph/Resolution/PubGrub/PubGrubDependencyResolver.swift index a8ae0399409..56e44240f01 100644 --- a/Sources/PackageGraph/Resolution/PubGrub/PubGrubDependencyResolver.swift +++ b/Sources/PackageGraph/Resolution/PubGrub/PubGrubDependencyResolver.swift @@ -44,10 +44,11 @@ public struct PubGrubDependencyResolver { private let lock = NSLock() - init(root: DependencyResolutionNode, - overriddenPackages: [PackageReference: (version: BoundVersion, products: ProductFilter)] = [:], - solution: PartialSolution = PartialSolution()) - { + init( + root: DependencyResolutionNode, + overriddenPackages: [PackageReference: (version: BoundVersion, products: ProductFilter)] = [:], + solution: PartialSolution = PartialSolution() + ) { self.root = root self.overriddenPackages = overriddenPackages self.solution = solution @@ -119,7 +120,8 @@ public struct PubGrubDependencyResolver { /// Resolver delegate private let delegate: DependencyResolverDelegate? - @available(*, + @available( + *, deprecated, renamed: "init(provider:resolvedPackages:skipDependenciesUpdates:prefetchBasedOnResolvedFile:observabilityScope:delegate:)", message: "Renamed for consistency with the actual name of the feature" @@ -275,25 +277,29 @@ public struct PubGrubDependencyResolver { flattenedAssignments[updatePackage] = (binding: boundVersion, products: products) } } - var finalAssignments: [DependencyResolverBinding] - = flattenedAssignments.keys.sorted(by: { $0.deprecatedName < $1.deprecatedName }).map { package in - let details = flattenedAssignments[package]! - return .init(package: package, boundVersion: details.binding, products: details.products) - } + var finalAssignments: [DependencyResolverBinding] = flattenedAssignments.keys.sorted(by: { $0.deprecatedName < $1.deprecatedName }).map { package in + let details = flattenedAssignments[package]! + return .init(package: package, boundVersion: details.binding, products: details.products) + } // Add overridden packages to the result. for (package, override) in state.overriddenPackages { let container = try await withCheckedThrowingContinuation { continuation in - self.provider.getContainer(for: package, completion: { - continuation.resume(with: $0) - }) + self.provider.getContainer( + for: package, + completion: { + continuation.resume(with: $0) + } + ) } let updatePackage = try await container.underlying.loadPackageReference(at: override.version) - finalAssignments.append(.init( + finalAssignments.append( + .init( package: updatePackage, boundVersion: override.version, products: override.products - )) + ) + ) } self.delegate?.solved(result: finalAssignments) @@ -405,9 +411,12 @@ public struct PubGrubDependencyResolver { // Process dependencies of this package, similar to the first phase but branch-based dependencies // are not allowed to contain local/unversioned packages. let container = try await withCheckedThrowingContinuation { continuation in - self.provider.getContainer(for: package, completion: { - continuation.resume(with: $0) - }) + self.provider.getContainer( + for: package, + completion: { + continuation.resume(with: $0) + } + ) } // If there is a pin for this revision-based dependency, get @@ -525,11 +534,13 @@ public struct PubGrubDependencyResolver { let rootCauseResult = self.propagate(state: state, incompatibility: rootCause) guard case .almostSatisfied(let pkg) = rootCauseResult else { - throw InternalError(""" - Expected root cause \(rootCause) to almost satisfy the \ - current partial solution: - \(state.solution.assignments.map { " * \($0.description)" }.joined(separator: "\n"))\n - """) + throw InternalError( + """ + Expected root cause \(rootCause) to almost satisfy the \ + current partial solution: + \(state.solution.assignments.map { " * \($0.description)" }.joined(separator: "\n"))\n + """ + ) } changed.removeAll(keepingCapacity: false) @@ -566,7 +577,6 @@ public struct PubGrubDependencyResolver { return .conflict } - state.derive(unsatisfiedTerm.inverse, cause: incompatibility) self.delegate?.derived(term: unsatisfiedTerm.inverse) return .almostSatisfied(node: unsatisfiedTerm.node) @@ -689,9 +699,12 @@ public struct PubGrubDependencyResolver { for term in terms { group.addTask { let container = try await withCheckedThrowingContinuation { continuation in - self.provider.getContainer(for: term.node.package, completion: { - continuation.resume(with: $0) - }) + self.provider.getContainer( + for: term.node.package, + completion: { + continuation.resume(with: $0) + } + ) } return try await (term, container.versionCount(term.requirement)) } @@ -752,13 +765,15 @@ public struct PubGrubDependencyResolver { state.addIncompatibility(incompatibility, at: .decisionMaking) // Check if this incompatibility will satisfy the solution. - haveConflict = haveConflict || incompatibility.terms.allSatisfy { - // We only need to check if the terms other than this package - // are satisfied because we _know_ that the terms matching - // this package will be satisfied if we make this version - // as a decision. - $0.node == pkgTerm.node || state.solution.satisfies($0) - } + haveConflict = + haveConflict + || incompatibility.terms.allSatisfy { + // We only need to check if the terms other than this package + // are satisfied because we _know_ that the terms matching + // this package will be satisfied if we make this version + // as a decision. + $0.node == pkgTerm.node || state.solution.satisfies($0) + } } // Decide this version if there was no conflict with its dependencies. diff --git a/Sources/PackageGraph/Resolution/PubGrub/PubGrubPackageContainer.swift b/Sources/PackageGraph/Resolution/PubGrub/PubGrubPackageContainer.swift index f82fa5d6d81..e608d73b60d 100644 --- a/Sources/PackageGraph/Resolution/PubGrub/PubGrubPackageContainer.swift +++ b/Sources/PackageGraph/Resolution/PubGrub/PubGrubPackageContainer.swift @@ -146,7 +146,7 @@ final class PubGrubPackageContainer { // Use the next patch since the upper bound needs to be inclusive here. upperBound = upperBound.nextPatch() } - return .range(lowerBound ..< upperBound.nextPatch()) + return .range(lowerBound.. .v5_9 { + if toolsVersion > .v5_9 { let container = try V3( pins: resolvedPackages, mirrors: mirrors, @@ -288,10 +289,10 @@ private struct ResolvedPackagesStorage { data = Data(bytes.contents) } #if !os(Windows) - // rdar://83646952: add newline for POSIXy systems - if data.last != 0x0A { - data.append(0x0A) - } + // rdar://83646952: add newline for POSIXy systems + if data.last != 0x0A { + data.append(0x0A) + } #endif try self.fileSystem.writeFileContents(self.path, data: data) } @@ -346,7 +347,7 @@ private struct ResolvedPackagesStorage { // backwards compatibility of JSON format func toLegacyJSON() -> JSON { .init([ - "pins": self.pins.map { $0.toLegacyJSON() }, + "pins": self.pins.map { $0.toLegacyJSON() } ]) } } @@ -393,7 +394,7 @@ private struct ResolvedPackagesStorage { case .version(let version, let revision) where revision != nil: self.version = version.description self.branch = nil - self.revision = revision! // nil guarded above in case + self.revision = revision! // nil guarded above in case case .branch(let branch, let revision): self.version = nil self.branch = branch @@ -453,7 +454,7 @@ private struct ResolvedPackagesStorage { location = url.absoluteString case .registry: kind = .registry - location = "" // FIXME: this is likely not correct + location = "" // FIXME: this is likely not correct default: throw StringError("invalid package type \(pin.packageRef.kind)") } @@ -522,7 +523,7 @@ extension ResolvedPackagesStore.ResolvedPackage { fileprivate init(_ pin: ResolvedPackagesStorage.V1.Pin, mirrors: DependencyMirrors) throws { // rdar://52529014, rdar://52529011: pin file should store the original location but remap when loading let location = mirrors.effective(for: pin.repositoryURL) - let identity = PackageIdentity(urlString: location) // FIXME: pin store should also encode identity + let identity = PackageIdentity(urlString: location) // FIXME: pin store should also encode identity var packageRef: PackageReference if let path = try? AbsolutePath(validating: location) { packageRef = .localSourceControl(identity: identity, path: path) diff --git a/Sources/PackageGraph/VersionSetSpecifier.swift b/Sources/PackageGraph/VersionSetSpecifier.swift index 12b92e0f268..51920cfc439 100644 --- a/Sources/PackageGraph/VersionSetSpecifier.swift +++ b/Sources/PackageGraph/VersionSetSpecifier.swift @@ -31,7 +31,7 @@ public enum VersionSetSpecifier: Hashable { } extension VersionSetSpecifier: Equatable { - public static func ==(lhs: VersionSetSpecifier, rhs: VersionSetSpecifier) -> Bool { + public static func == (lhs: VersionSetSpecifier, rhs: VersionSetSpecifier) -> Bool { switch (lhs, rhs) { // Basic cases. case (.any, .any): @@ -121,14 +121,14 @@ extension VersionSetSpecifier { // 1.0.0..<1.0.1 U 1.0.1..<1.0.1 is 1.0.0..<1.0.2 let version = range.lowerBound if last.upperBound == version { - newResult = last.lowerBound ..< version.nextPatch() + newResult = last.lowerBound.. String { let encoder = JSONEncoder() let data = try encoder.encode(self) diff --git a/Sources/PackageLoading/Diagnostics.swift b/Sources/PackageLoading/Diagnostics.swift index eb3bbde4777..7955c537d21 100644 --- a/Sources/PackageLoading/Diagnostics.swift +++ b/Sources/PackageLoading/Diagnostics.swift @@ -38,7 +38,7 @@ extension Basics.Diagnostic { case .library(.automatic): typeString = "" case .executable, .snippet, .plugin, .test, .macro, - .library(.dynamic), .library(.static): + .library(.dynamic), .library(.static): typeString = " (\(product.type))" } @@ -74,17 +74,21 @@ extension Basics.Diagnostic { } static func executableProductTargetNotExecutable(product: String, target: String) -> Self { - .error(""" + .error( + """ executable product '\(product)' expects target '\(target)' to be executable; an executable target requires \ a 'main.swift' file - """) + """ + ) } static func executableProductWithoutExecutableTarget(product: String) -> Self { - .error(""" + .error( + """ executable product '\(product)' should have one executable target; an executable target requires a \ 'main.swift' file - """) + """ + ) } static func executableProductWithMoreThanOneExecutableTarget(product: String) -> Self { @@ -123,10 +127,12 @@ extension Basics.Diagnostic { path: RelativePath, targetName: String ) -> Self { - .error(""" + .error( + """ resource '\(path)' in target '\(targetName)' is forbidden; Info.plist is not supported as a top-level \ resource file in the resources bundle - """) + """ + ) } static func copyConflictWithLocalizationDirectory(path: RelativePath, targetName: String) -> Self { @@ -138,17 +144,21 @@ extension Basics.Diagnostic { } static func localizationAmbiguity(path: RelativePath, targetName: String) -> Self { - .error(""" + .error( + """ resource '\(path)' in target '\(targetName)' is in a localization directory and has an explicit \ localization declaration in the package manifest; choose one or the other to avoid any ambiguity - """) + """ + ) } static func localizedAndUnlocalizedVariants(resource: String, targetName: String) -> Self { - .warning(""" + .warning( + """ resource '\(resource)' in target '\(targetName)' has both localized and un-localized variants; the \ localized variants will never be chosen - """) + """ + ) } } diff --git a/Sources/PackageLoading/ManifestJSONParser.swift b/Sources/PackageLoading/ManifestJSONParser.swift index 07ca0e6eacc..4a2dbcd6a79 100644 --- a/Sources/PackageLoading/ManifestJSONParser.swift +++ b/Sources/PackageLoading/ManifestJSONParser.swift @@ -194,8 +194,8 @@ enum ManifestJSONParser { let pluginCapability = target.pluginCapability.map { TargetDescription.PluginCapability($0) } let dependencies = try target.dependencies.map { try TargetDescription.Dependency($0, identityResolver: identityResolver) } - try target.sources?.forEach{ _ = try RelativePath(validating: $0) } - try target.exclude.forEach{ _ = try RelativePath(validating: $0) } + try target.sources?.forEach { _ = try RelativePath(validating: $0) } + try target.exclude.forEach { _ = try RelativePath(validating: $0) } let pluginUsages = target.pluginUsages?.map { TargetDescription.PluginUsage.init($0) } @@ -303,192 +303,192 @@ extension PackageDependency.Registry.Requirement { } #if ENABLE_APPLE_PRODUCT_TYPES -extension ProductSetting { - init(_ setting: Serialization.ProductSetting) { - switch setting { - case .bundleIdentifier(let value): - self = .bundleIdentifier(value) - case .teamIdentifier(let value): - self = .teamIdentifier(value) - case .displayVersion(let value): - self = .displayVersion(value) - case .bundleVersion(let value): - self = .bundleVersion(value) - case .iOSAppInfo(let appInfo): - self = .iOSAppInfo(.init(appInfo)) + extension ProductSetting { + init(_ setting: Serialization.ProductSetting) { + switch setting { + case .bundleIdentifier(let value): + self = .bundleIdentifier(value) + case .teamIdentifier(let value): + self = .teamIdentifier(value) + case .displayVersion(let value): + self = .displayVersion(value) + case .bundleVersion(let value): + self = .bundleVersion(value) + case .iOSAppInfo(let appInfo): + self = .iOSAppInfo(.init(appInfo)) + } } } -} - -extension ProductSetting.IOSAppInfo { - init(_ appInfo: Serialization.ProductSetting.IOSAppInfo) { - self.init( - appIcon: appInfo.appIcon.map { .init($0) }, - accentColor: appInfo.accentColor.map { .init($0) }, - supportedDeviceFamilies: appInfo.supportedDeviceFamilies.map { .init($0) }, - supportedInterfaceOrientations: appInfo.supportedInterfaceOrientations.map { .init($0) }, - capabilities: appInfo.capabilities.map { .init($0) }, - appCategory: appInfo.appCategory.map { .init($0) }, - additionalInfoPlistContentFilePath: appInfo.additionalInfoPlistContentFilePath - ) - } -} -extension ProductSetting.IOSAppInfo.DeviceFamily { - init(_ deviceFamily: Serialization.ProductSetting.IOSAppInfo.DeviceFamily) { - switch deviceFamily { - case .phone: self = .phone - case .pad: self = .pad - case .mac: self = .mac + extension ProductSetting.IOSAppInfo { + init(_ appInfo: Serialization.ProductSetting.IOSAppInfo) { + self.init( + appIcon: appInfo.appIcon.map { .init($0) }, + accentColor: appInfo.accentColor.map { .init($0) }, + supportedDeviceFamilies: appInfo.supportedDeviceFamilies.map { .init($0) }, + supportedInterfaceOrientations: appInfo.supportedInterfaceOrientations.map { .init($0) }, + capabilities: appInfo.capabilities.map { .init($0) }, + appCategory: appInfo.appCategory.map { .init($0) }, + additionalInfoPlistContentFilePath: appInfo.additionalInfoPlistContentFilePath + ) } } -} -extension ProductSetting.IOSAppInfo.DeviceFamilyCondition { - init(_ condition: Serialization.ProductSetting.IOSAppInfo.DeviceFamilyCondition) { - self.init(deviceFamilies: condition.deviceFamilies.map { .init($0) }) + extension ProductSetting.IOSAppInfo.DeviceFamily { + init(_ deviceFamily: Serialization.ProductSetting.IOSAppInfo.DeviceFamily) { + switch deviceFamily { + case .phone: self = .phone + case .pad: self = .pad + case .mac: self = .mac + } + } } -} -extension ProductSetting.IOSAppInfo.InterfaceOrientation { - init(_ interfaceOrientation: Serialization.ProductSetting.IOSAppInfo.InterfaceOrientation) { - switch interfaceOrientation { - case .portrait(let condition): - self = .portrait(condition: condition.map { .init($0) }) - case .portraitUpsideDown(let condition): - self = .portraitUpsideDown(condition: condition.map { .init($0) }) - case .landscapeRight(let condition): - self = .landscapeRight(condition: condition.map { .init($0) }) - case .landscapeLeft(let condition): - self = .landscapeLeft(condition: condition.map { .init($0) }) + extension ProductSetting.IOSAppInfo.DeviceFamilyCondition { + init(_ condition: Serialization.ProductSetting.IOSAppInfo.DeviceFamilyCondition) { + self.init(deviceFamilies: condition.deviceFamilies.map { .init($0) }) } } -} -extension ProductSetting.IOSAppInfo.AppIcon { - init(_ icon: Serialization.ProductSetting.IOSAppInfo.AppIcon) { - switch icon { - case .placeholder(icon: let icon): - self = .placeholder(icon: .init(icon)) - case .asset(let name): - self = .asset(name: name) + extension ProductSetting.IOSAppInfo.InterfaceOrientation { + init(_ interfaceOrientation: Serialization.ProductSetting.IOSAppInfo.InterfaceOrientation) { + switch interfaceOrientation { + case .portrait(let condition): + self = .portrait(condition: condition.map { .init($0) }) + case .portraitUpsideDown(let condition): + self = .portraitUpsideDown(condition: condition.map { .init($0) }) + case .landscapeRight(let condition): + self = .landscapeRight(condition: condition.map { .init($0) }) + case .landscapeLeft(let condition): + self = .landscapeLeft(condition: condition.map { .init($0) }) + } } } -} -extension ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon { - init(_ icon: Serialization.ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon) { - self.init(rawValue: icon.rawValue) + extension ProductSetting.IOSAppInfo.AppIcon { + init(_ icon: Serialization.ProductSetting.IOSAppInfo.AppIcon) { + switch icon { + case .placeholder(icon: let icon): + self = .placeholder(icon: .init(icon)) + case .asset(let name): + self = .asset(name: name) + } + } } -} -extension ProductSetting.IOSAppInfo.AccentColor { - init(_ color: Serialization.ProductSetting.IOSAppInfo.AccentColor) { - switch color { - case .presetColor(let color): - self = .presetColor(presetColor: .init(color)) - case .asset(let name): - self = .asset(name: name) + extension ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon { + init(_ icon: Serialization.ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon) { + self.init(rawValue: icon.rawValue) } } -} -extension ProductSetting.IOSAppInfo.AccentColor.PresetColor { - init(_ color: Serialization.ProductSetting.IOSAppInfo.AccentColor.PresetColor) { - self.init(rawValue: color.rawValue) + extension ProductSetting.IOSAppInfo.AccentColor { + init(_ color: Serialization.ProductSetting.IOSAppInfo.AccentColor) { + switch color { + case .presetColor(let color): + self = .presetColor(presetColor: .init(color)) + case .asset(let name): + self = .asset(name: name) + } + } } -} -extension ProductSetting.IOSAppInfo.Capability { - init(_ capability: Serialization.ProductSetting.IOSAppInfo.Capability) { - switch capability { - case .appTransportSecurity(configuration: let configuration, let condition): - self.init(purpose: "appTransportSecurity", appTransportSecurityConfiguration: .init(configuration), condition: condition.map { .init($0) }) - case .bluetoothAlways(purposeString: let purposeString, let condition): - self.init(purpose: "bluetoothAlways", purposeString: purposeString, condition: condition.map { .init($0) }) - case .calendars(purposeString: let purposeString, let condition): - self.init(purpose: "calendars", purposeString: purposeString, condition: condition.map { .init($0) }) - case .camera(purposeString: let purposeString, let condition): - self.init(purpose: "camera", purposeString: purposeString, condition: condition.map { .init($0) }) - case .contacts(purposeString: let purposeString, let condition): - self.init(purpose: "contacts", purposeString: purposeString, condition: condition.map { .init($0) }) - case .faceID(purposeString: let purposeString, let condition): - self.init(purpose: "faceID", purposeString: purposeString, condition: condition.map { .init($0) }) - case .fileAccess(let location, mode: let mode, let condition): - self.init(purpose: "fileAccess", fileAccessLocation: location.rawValue, fileAccessMode: mode.rawValue, condition: condition.map { .init($0) }) - case .incomingNetworkConnections(let condition): - self.init(purpose: "incomingNetworkConnections", condition: condition.map { .init($0) }) - case .localNetwork(purposeString: let purposeString, bonjourServiceTypes: let bonjourServiceTypes, let condition): - self.init(purpose: "localNetwork", purposeString: purposeString, bonjourServiceTypes: bonjourServiceTypes, condition: condition.map { .init($0) }) - case .locationAlwaysAndWhenInUse(purposeString: let purposeString, let condition): - self.init(purpose: "locationAlwaysAndWhenInUse", purposeString: purposeString, condition: condition.map { .init($0) }) - case .locationWhenInUse(purposeString: let purposeString, let condition): - self.init(purpose: "locationWhenInUse", purposeString: purposeString, condition: condition.map { .init($0) }) - case .mediaLibrary(purposeString: let purposeString, let condition): - self.init(purpose: "mediaLibrary", purposeString: purposeString, condition: condition.map { .init($0) }) - case .microphone(purposeString: let purposeString, let condition): - self.init(purpose: "microphone", purposeString: purposeString, condition: condition.map { .init($0) }) - case .motion(purposeString: let purposeString, let condition): - self.init(purpose: "motion", purposeString: purposeString, condition: condition.map { .init($0) }) - case .nearbyInteractionAllowOnce(purposeString: let purposeString, let condition): - self.init(purpose: "nearbyInteractionAllowOnce", purposeString: purposeString, condition: condition.map { .init($0) }) - case .outgoingNetworkConnections(let condition): - self.init(purpose: "outgoingNetworkConnections", condition: condition.map { .init($0) }) - case .photoLibrary(purposeString: let purposeString, let condition): - self.init(purpose: "photoLibrary", purposeString: purposeString, condition: condition.map { .init($0) }) - case .photoLibraryAdd(purposeString: let purposeString, let condition): - self.init(purpose: "photoLibraryAdd", purposeString: purposeString, condition: condition.map { .init($0) }) - case .reminders(purposeString: let purposeString, let condition): - self.init(purpose: "reminders", purposeString: purposeString, condition: condition.map { .init($0) }) - case .speechRecognition(purposeString: let purposeString, let condition): - self.init(purpose: "speechRecognition", purposeString: purposeString, condition: condition.map { .init($0) }) - case .userTracking(purposeString: let purposeString, let condition): - self.init(purpose: "userTracking", purposeString: purposeString, condition: condition.map { .init($0) }) + extension ProductSetting.IOSAppInfo.AccentColor.PresetColor { + init(_ color: Serialization.ProductSetting.IOSAppInfo.AccentColor.PresetColor) { + self.init(rawValue: color.rawValue) + } + } + + extension ProductSetting.IOSAppInfo.Capability { + init(_ capability: Serialization.ProductSetting.IOSAppInfo.Capability) { + switch capability { + case .appTransportSecurity(configuration: let configuration, let condition): + self.init(purpose: "appTransportSecurity", appTransportSecurityConfiguration: .init(configuration), condition: condition.map { .init($0) }) + case .bluetoothAlways(purposeString: let purposeString, let condition): + self.init(purpose: "bluetoothAlways", purposeString: purposeString, condition: condition.map { .init($0) }) + case .calendars(purposeString: let purposeString, let condition): + self.init(purpose: "calendars", purposeString: purposeString, condition: condition.map { .init($0) }) + case .camera(purposeString: let purposeString, let condition): + self.init(purpose: "camera", purposeString: purposeString, condition: condition.map { .init($0) }) + case .contacts(purposeString: let purposeString, let condition): + self.init(purpose: "contacts", purposeString: purposeString, condition: condition.map { .init($0) }) + case .faceID(purposeString: let purposeString, let condition): + self.init(purpose: "faceID", purposeString: purposeString, condition: condition.map { .init($0) }) + case .fileAccess(let location, mode: let mode, let condition): + self.init(purpose: "fileAccess", fileAccessLocation: location.rawValue, fileAccessMode: mode.rawValue, condition: condition.map { .init($0) }) + case .incomingNetworkConnections(let condition): + self.init(purpose: "incomingNetworkConnections", condition: condition.map { .init($0) }) + case .localNetwork(purposeString: let purposeString, bonjourServiceTypes: let bonjourServiceTypes, let condition): + self.init(purpose: "localNetwork", purposeString: purposeString, bonjourServiceTypes: bonjourServiceTypes, condition: condition.map { .init($0) }) + case .locationAlwaysAndWhenInUse(purposeString: let purposeString, let condition): + self.init(purpose: "locationAlwaysAndWhenInUse", purposeString: purposeString, condition: condition.map { .init($0) }) + case .locationWhenInUse(purposeString: let purposeString, let condition): + self.init(purpose: "locationWhenInUse", purposeString: purposeString, condition: condition.map { .init($0) }) + case .mediaLibrary(purposeString: let purposeString, let condition): + self.init(purpose: "mediaLibrary", purposeString: purposeString, condition: condition.map { .init($0) }) + case .microphone(purposeString: let purposeString, let condition): + self.init(purpose: "microphone", purposeString: purposeString, condition: condition.map { .init($0) }) + case .motion(purposeString: let purposeString, let condition): + self.init(purpose: "motion", purposeString: purposeString, condition: condition.map { .init($0) }) + case .nearbyInteractionAllowOnce(purposeString: let purposeString, let condition): + self.init(purpose: "nearbyInteractionAllowOnce", purposeString: purposeString, condition: condition.map { .init($0) }) + case .outgoingNetworkConnections(let condition): + self.init(purpose: "outgoingNetworkConnections", condition: condition.map { .init($0) }) + case .photoLibrary(purposeString: let purposeString, let condition): + self.init(purpose: "photoLibrary", purposeString: purposeString, condition: condition.map { .init($0) }) + case .photoLibraryAdd(purposeString: let purposeString, let condition): + self.init(purpose: "photoLibraryAdd", purposeString: purposeString, condition: condition.map { .init($0) }) + case .reminders(purposeString: let purposeString, let condition): + self.init(purpose: "reminders", purposeString: purposeString, condition: condition.map { .init($0) }) + case .speechRecognition(purposeString: let purposeString, let condition): + self.init(purpose: "speechRecognition", purposeString: purposeString, condition: condition.map { .init($0) }) + case .userTracking(purposeString: let purposeString, let condition): + self.init(purpose: "userTracking", purposeString: purposeString, condition: condition.map { .init($0) }) + } } } -} -extension ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration { - init(_ configuration: Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration) { - self.init( - allowsArbitraryLoadsInWebContent: configuration.allowsArbitraryLoadsInWebContent, - allowsArbitraryLoadsForMedia: configuration.allowsArbitraryLoadsForMedia, - allowsLocalNetworking: configuration.allowsLocalNetworking, - exceptionDomains: configuration.exceptionDomains?.map { .init($0) }, - pinnedDomains: configuration.pinnedDomains?.map { .init($0) } - ) + extension ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration { + init(_ configuration: Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration) { + self.init( + allowsArbitraryLoadsInWebContent: configuration.allowsArbitraryLoadsInWebContent, + allowsArbitraryLoadsForMedia: configuration.allowsArbitraryLoadsForMedia, + allowsLocalNetworking: configuration.allowsLocalNetworking, + exceptionDomains: configuration.exceptionDomains?.map { .init($0) }, + pinnedDomains: configuration.pinnedDomains?.map { .init($0) } + ) + } } -} -extension ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.ExceptionDomain { - init(_ exceptionDomain: Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.ExceptionDomain) { - self.init( - domainName: exceptionDomain.domainName, - includesSubdomains: exceptionDomain.includesSubdomains, - exceptionAllowsInsecureHTTPLoads: exceptionDomain.exceptionAllowsInsecureHTTPLoads, - exceptionMinimumTLSVersion: exceptionDomain.exceptionMinimumTLSVersion, - exceptionRequiresForwardSecrecy: exceptionDomain.exceptionRequiresForwardSecrecy, - requiresCertificateTransparency: exceptionDomain.requiresCertificateTransparency - ) + extension ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.ExceptionDomain { + init(_ exceptionDomain: Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.ExceptionDomain) { + self.init( + domainName: exceptionDomain.domainName, + includesSubdomains: exceptionDomain.includesSubdomains, + exceptionAllowsInsecureHTTPLoads: exceptionDomain.exceptionAllowsInsecureHTTPLoads, + exceptionMinimumTLSVersion: exceptionDomain.exceptionMinimumTLSVersion, + exceptionRequiresForwardSecrecy: exceptionDomain.exceptionRequiresForwardSecrecy, + requiresCertificateTransparency: exceptionDomain.requiresCertificateTransparency + ) + } } -} -extension ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.PinnedDomain { - init(_ pinnedDomain: Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.PinnedDomain) { - self.init( - domainName: pinnedDomain.domainName, - includesSubdomains: pinnedDomain.includesSubdomains, - pinnedCAIdentities: pinnedDomain.pinnedCAIdentities, - pinnedLeafIdentities: pinnedDomain.pinnedLeafIdentities - ) + extension ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.PinnedDomain { + init(_ pinnedDomain: Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.PinnedDomain) { + self.init( + domainName: pinnedDomain.domainName, + includesSubdomains: pinnedDomain.includesSubdomains, + pinnedCAIdentities: pinnedDomain.pinnedCAIdentities, + pinnedLeafIdentities: pinnedDomain.pinnedLeafIdentities + ) + } } -} -extension ProductSetting.IOSAppInfo.AppCategory { - init(_ category: Serialization.ProductSetting.IOSAppInfo.AppCategory) { - self.init(rawValue: category.rawValue) + extension ProductSetting.IOSAppInfo.AppCategory { + init(_ category: Serialization.ProductSetting.IOSAppInfo.AppCategory) { + self.init(rawValue: category.rawValue) + } } -} #endif extension ProductDescription { @@ -503,9 +503,9 @@ extension ProductDescription { productType = .library(.init(type)) } #if ENABLE_APPLE_PRODUCT_TYPES - try self.init(name: product.name, type: productType, targets: product.targets, settings: product.settings.map { .init($0) }) + try self.init(name: product.name, type: productType, targets: product.targets, settings: product.settings.map { .init($0) }) #else - try self.init(name: product.name, type: productType, targets: product.targets) + try self.init(name: product.name, type: productType, targets: product.targets) #endif } } @@ -672,7 +672,7 @@ extension PlatformDescription { self.init( name: platformName, version: version.joined(separator: "."), - options: options.map{ String($0) } + options: options.map { String($0) } ) } } @@ -681,7 +681,7 @@ extension TargetBuildSettingDescription.Kind { static func from(_ name: String, values: [String]) throws -> Self { // Diagnose invalid values. for item in values { - let groups = ManifestJSONParser.invalidValueRegex.matchGroups(in: item).flatMap{ $0 } + let groups = ManifestJSONParser.invalidValueRegex.matchGroups(in: item).flatMap { $0 } if !groups.isEmpty { let error = "the build setting '\(name)' contains invalid component(s): \(groups.joined(separator: " "))" throw ManifestParseError.runtimeManifestErrors([error]) @@ -862,7 +862,6 @@ extension PackageDependency.Trait { } } - extension PackageDependency.Trait.Condition { init(_ condition: Serialization.PackageDependency.Trait.Condition) { self.init(traits: condition.traits) @@ -880,7 +879,7 @@ extension MappablePackageDependency { path: path ), productFilter: .everything, - traits: seed.traits.flatMap { Set($0.map { PackageDependency.Trait.init($0) } ) } + traits: seed.traits.flatMap { Set($0.map { PackageDependency.Trait.init($0) }) } ) case .sourceControl(let name, let location, let requirement): self.init( @@ -891,7 +890,7 @@ extension MappablePackageDependency { requirement: .init(requirement) ), productFilter: .everything, - traits: seed.traits.flatMap { Set($0.map { PackageDependency.Trait.init($0) } ) } + traits: seed.traits.flatMap { Set($0.map { PackageDependency.Trait.init($0) }) } ) case .registry(let id, let requirement): self.init( @@ -901,7 +900,7 @@ extension MappablePackageDependency { requirement: .init(requirement) ), productFilter: .everything, - traits: seed.traits.flatMap { Set($0.map { PackageDependency.Trait.init($0) } ) } + traits: seed.traits.flatMap { Set($0.map { PackageDependency.Trait.init($0) }) } ) } } diff --git a/Sources/PackageLoading/ManifestLoader+Validation.swift b/Sources/PackageLoading/ManifestLoader+Validation.swift index cecc121d5bf..417b7887e73 100644 --- a/Sources/PackageLoading/ManifestLoader+Validation.swift +++ b/Sources/PackageLoading/ManifestLoader+Validation.swift @@ -63,9 +63,9 @@ public struct ManifestValidator { return diagnostics } - private func validateProducts() -> [Basics.Diagnostic] { + private func validateProducts() -> [Basics.Diagnostic] { var diagnostics = [Basics.Diagnostic]() - + for product in self.manifest.products { // Check that the product contains targets. guard !product.targets.isEmpty else { @@ -169,10 +169,12 @@ public struct ManifestValidator { let validExtensions = Self.supportedLocalBinaryDependencyExtensions guard let fileExtension = relativePath.extension, validExtensions.contains(fileExtension) else { - diagnostics.append(.unsupportedBinaryLocationExtension( - targetName: target.name, - validExtensions: validExtensions - )) + diagnostics.append( + .unsupportedBinaryLocationExtension( + targetName: target.name, + validExtensions: validExtensions + ) + ) continue } } else if target.isRemote { @@ -193,18 +195,22 @@ public struct ManifestValidator { let validSchemes = ["https"] guard url.scheme.map({ validSchemes.contains($0) }) ?? false else { - diagnostics.append(.invalidBinaryURLScheme( - targetName: target.name, - validSchemes: validSchemes - )) + diagnostics.append( + .invalidBinaryURLScheme( + targetName: target.name, + validSchemes: validSchemes + ) + ) continue } guard Self.supportedRemoteBinaryDependencyExtensions.contains(url.pathExtension) else { - diagnostics.append(.unsupportedBinaryLocationExtension( - targetName: target.name, - validExtensions: Self.supportedRemoteBinaryDependencyExtensions - )) + diagnostics.append( + .unsupportedBinaryLocationExtension( + targetName: target.name, + validExtensions: Self.supportedRemoteBinaryDependencyExtensions + ) + ) continue } @@ -229,23 +235,24 @@ public struct ManifestValidator { break case .product(_, let packageName, _, _): if self.manifest.packageDependency(referencedBy: targetDependency) == nil { - diagnostics.append(.unknownTargetPackageDependency( - packageName: packageName, - targetName: target.name, - validPackages: self.manifest.dependencies - )) + diagnostics.append( + .unknownTargetPackageDependency( + packageName: packageName, + targetName: target.name, + validPackages: self.manifest.dependencies + ) + ) } case .byName(let name, _): // Don't diagnose root manifests so we can emit a better diagnostic during package loading. - if !self.manifest.packageKind.isRoot && - !self.manifest.targetMap.keys.contains(name) && - self.manifest.packageDependency(referencedBy: targetDependency) == nil - { - diagnostics.append(.unknownTargetDependency( - dependency: name, - targetName: target.name, - validDependencies: self.manifest.dependencies - )) + if !self.manifest.packageKind.isRoot && !self.manifest.targetMap.keys.contains(name) && self.manifest.packageDependency(referencedBy: targetDependency) == nil { + diagnostics.append( + .unknownTargetDependency( + dependency: name, + targetName: target.name, + validDependencies: self.manifest.dependencies + ) + ) } } } @@ -338,10 +345,12 @@ extension Basics.Diagnostic { } static func invalidLanguageTag(_ languageTag: String) -> Self { - .error(""" + .error( + """ invalid language tag '\(languageTag)'; the pattern for language tags is groups of latin characters and \ digits separated by hyphens - """) + """ + ) } static func errorSuffix(_ error: Error?) -> String { diff --git a/Sources/PackageLoading/ManifestLoader.swift b/Sources/PackageLoading/ManifestLoader.swift index c3ee04f840e..bc2eb9c8015 100644 --- a/Sources/PackageLoading/ManifestLoader.swift +++ b/Sources/PackageLoading/ManifestLoader.swift @@ -26,7 +26,7 @@ import enum TSCUtility.Diagnostics import struct TSCUtility.Version #if os(Windows) -import WinSDK + import WinSDK #endif extension AbsolutePath { @@ -35,17 +35,17 @@ extension AbsolutePath { /// path normalization rules. In the case that the path is a long path, the /// path will use the extended path syntax (UNC style, NT Path). internal var _normalized: String { -#if os(Windows) - return self.pathString.withCString(encodedAs: UTF16.self) { pwszPath in - let dwLength = GetFullPathNameW(pwszPath, 0, nil, nil) - return withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) { - _ = GetFullPathNameW(pwszPath, dwLength, $0.baseAddress, nil) - return String(decodingCString: $0.baseAddress!, as: UTF16.self) + #if os(Windows) + return self.pathString.withCString(encodedAs: UTF16.self) { pwszPath in + let dwLength = GetFullPathNameW(pwszPath, 0, nil, nil) + return withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) { + _ = GetFullPathNameW(pwszPath, dwLength, $0.baseAddress, nil) + return String(decodingCString: $0.baseAddress!, as: UTF16.self) + } } - } -#else - return self.pathString -#endif + #else + return self.pathString + #endif } } @@ -345,20 +345,25 @@ public final class ManifestLoader: ManifestLoaderProtocol { var products = parsedManifest.products var targets = parsedManifest.targets if products.isEmpty, targets.isEmpty, - fileSystem.isFile(manifestPath.parentDirectory.appending(component: moduleMapFilename)) { - try products.append(ProductDescription( - name: parsedManifest.name, - type: .library(.automatic), - targets: [parsedManifest.name]) + fileSystem.isFile(manifestPath.parentDirectory.appending(component: moduleMapFilename)) + { + try products.append( + ProductDescription( + name: parsedManifest.name, + type: .library(.automatic), + targets: [parsedManifest.name] + ) + ) + targets.append( + try TargetDescription( + name: parsedManifest.name, + path: "", + type: .system, + packageAccess: false, + pkgConfig: parsedManifest.pkgConfig, + providers: parsedManifest.providers + ) ) - targets.append(try TargetDescription( - name: parsedManifest.name, - path: "", - type: .system, - packageAccess: false, - pkgConfig: parsedManifest.pkgConfig, - providers: parsedManifest.providers - )) } let manifest = Manifest( @@ -518,7 +523,6 @@ public final class ManifestLoader: ManifestLoaderProtocol { } } - do { // try to get it from the cache if let evaluationResult = try dbCache?.get(key: key.sha256Checksum), let manifestJSON = evaluationResult.manifestJSON, !manifestJSON.isEmpty { @@ -536,7 +540,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { emitCompilerOutput: false, observabilityScope: observabilityScope, delegate: delegate, - delegateQueue: delegateQueue // Pass the delegate queue + delegateQueue: delegateQueue // Pass the delegate queue ) // Store in memory cache if enabled if self.useInMemoryCache { @@ -562,7 +566,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { toolsVersion: key.toolsVersion, observabilityScope: observabilityScope, delegate: delegate, - delegateQueue: delegateQueue // Pass the delegate queue + delegateQueue: delegateQueue // Pass the delegate queue ) // only cache successfully parsed manifests @@ -607,12 +611,13 @@ public final class ManifestLoader: ManifestLoaderProtocol { } // Allowed are the expected defaults, plus anything allowed by the configured restrictions. - let allowedImports = [ - "PackageDescription", - "Swift", - "SwiftOnoneSupport", - "_SwiftConcurrencyShims" - ] + importRestrictions.allowedImports + let allowedImports = + [ + "PackageDescription", + "Swift", + "SwiftOnoneSupport", + "_SwiftConcurrencyShims", + ] + importRestrictions.allowedImports let importScanner = SwiftcImportScanner( swiftCompilerEnvironment: self.toolchain.swiftCompilerEnvironment, @@ -707,9 +712,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { // FIXME: Workaround for the module cache bug that's been haunting Swift CI // - let moduleCachePath = try ( - Environment.current["SWIFTPM_MODULECACHE_OVERRIDE"] ?? - Environment.current["SWIFTPM_TESTS_MODULECACHE"]).flatMap { try AbsolutePath(validating: $0) } + let moduleCachePath = try (Environment.current["SWIFTPM_MODULECACHE_OVERRIDE"] ?? Environment.current["SWIFTPM_TESTS_MODULECACHE"]).flatMap { try AbsolutePath(validating: $0) } var cmd: [String] = [] cmd += [self.toolchain.swiftCompilerPathForManifests.pathString] @@ -727,31 +730,31 @@ public final class ManifestLoader: ManifestLoaderProtocol { ] // Explicitly link `AppleProductTypes` since auto-linking won't work here. -#if ENABLE_APPLE_PRODUCT_TYPES - cmd += ["-framework", "AppleProductTypes"] -#else - cmd += ["-framework", "PackageDescription"] -#endif + #if ENABLE_APPLE_PRODUCT_TYPES + cmd += ["-framework", "AppleProductTypes"] + #else + cmd += ["-framework", "PackageDescription"] + #endif } else { cmd += [ "-L", runtimePath.pathString, "-lPackageDescription", ] -#if !os(Windows) - // -rpath argument is not supported on Windows, - // so we add runtimePath to PATH when executing the manifest instead - cmd += ["-Xlinker", "-rpath", "-Xlinker", runtimePath.pathString] -#endif + #if !os(Windows) + // -rpath argument is not supported on Windows, + // so we add runtimePath to PATH when executing the manifest instead + cmd += ["-Xlinker", "-rpath", "-Xlinker", runtimePath.pathString] + #endif } // Use the same minimum deployment target as the PackageDescription library (with a fallback to the default host triple). -#if os(macOS) - if let version = self.toolchain.swiftPMLibrariesLocation.manifestLibraryMinimumDeploymentTarget?.versionString { - cmd += ["-target", "\(self.toolchain.targetTriple.tripleString(forPlatformVersion: version))"] - } else { - cmd += ["-target", self.toolchain.targetTriple.tripleString] - } -#endif + #if os(macOS) + if let version = self.toolchain.swiftPMLibrariesLocation.manifestLibraryMinimumDeploymentTarget?.versionString { + cmd += ["-target", "\(self.toolchain.targetTriple.tripleString(forPlatformVersion: version))"] + } else { + cmd += ["-target", self.toolchain.targetTriple.tripleString] + } + #endif // Add any extra flags required as indicated by the ManifestLoader. cmd += self.toolchain.swiftCompilerFlags @@ -778,9 +781,9 @@ public final class ManifestLoader: ManifestLoaderProtocol { return try await Basics.withTemporaryDirectory(removeTreeOnDeinit: true) { tmpDir in // Set path to compiled manifest executable. #if os(Windows) - let executableSuffix = ".exe" + let executableSuffix = ".exe" #else - let executableSuffix = "" + let executableSuffix = "" #endif let compiledManifestFile = tmpDir.appending("\(packageIdentity)-manifest\(executableSuffix)") cmd += ["-o", compiledManifestFile.pathString] @@ -798,8 +801,8 @@ public final class ManifestLoader: ManifestLoaderProtocol { let compileStart = DispatchTime.now() let compilerResult: AsyncProcessResult do { - compilerResult = try await AsyncProcess.popen(arguments: cmd, environment: self.toolchain.swiftCompilerEnvironment) - evaluationResult.compilerOutput = try (compilerResult.utf8Output() + compilerResult.utf8stderrOutput()).spm_chuzzle() + compilerResult = try await AsyncProcess.popen(arguments: cmd, environment: self.toolchain.swiftCompilerEnvironment) + evaluationResult.compilerOutput = try (compilerResult.utf8Output() + compilerResult.utf8stderrOutput()).spm_chuzzle() } catch { delegateQueue?.async { [delegate = self.delegate] in delegate?.didCompile( @@ -809,7 +812,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { duration: compileStart.distance(to: .now()) ) } - throw error // Re-throw process errors + throw error // Re-throw process errors } delegateQueue?.async { [delegate = self.delegate] in @@ -824,27 +827,26 @@ public final class ManifestLoader: ManifestLoaderProtocol { // Return now if there was a compilation error. if compilerResult.exitStatus != .terminated(code: 0) { // If there's compiler output, it's a format error. Otherwise, maybe something else went wrong. - evaluationResult.errorOutput = evaluationResult.compilerOutput ?? "Manifest compilation failed with exit status \(compilerResult.exitStatus)" - return evaluationResult // Return the result containing the error output + evaluationResult.errorOutput = evaluationResult.compilerOutput ?? "Manifest compilation failed with exit status \(compilerResult.exitStatus)" + return evaluationResult // Return the result containing the error output } // Pass an open file descriptor of a file to which the JSON representation of the manifest will be written. let jsonOutputFile = tmpDir.appending("\(packageIdentity)-output.json") guard let jsonOutputFileDesc = fopen(jsonOutputFile.pathString, "w") else { - throw StringError("couldn't create the manifest's JSON output file") + throw StringError("couldn't create the manifest's JSON output file") } // Ensure the file is closed defer { fclose(jsonOutputFileDesc) } - var runCmd = [compiledManifestFile.pathString] #if os(Windows) - // NOTE: `_get_osfhandle` returns a non-owning, unsafe, - // unretained HANDLE. DO NOT invoke `CloseHandle` on `hFile`. - let hFile: Int = _get_osfhandle(_fileno(jsonOutputFileDesc)) - runCmd += ["-handle", "\(String(hFile, radix: 16))"] + // NOTE: `_get_osfhandle` returns a non-owning, unsafe, + // unretained HANDLE. DO NOT invoke `CloseHandle` on `hFile`. + let hFile: Int = _get_osfhandle(_fileno(jsonOutputFileDesc)) + runCmd += ["-handle", "\(String(hFile, radix: 16))"] #else - runCmd += ["-fileno", "\(fileno(jsonOutputFileDesc))"] + runCmd += ["-fileno", "\(fileno(jsonOutputFileDesc))"] #endif do { @@ -870,19 +872,19 @@ public final class ManifestLoader: ManifestLoaderProtocol { ) runCmd += ["-context", try contextModel.encode()] } catch { - throw error // Re-throw encoding errors + throw error // Re-throw encoding errors } // If enabled, run command in a sandbox. // This provides some safety against arbitrary code execution when parsing manifest files. // We only allow the permissions which are absolutely necessary. if self.isManifestSandboxEnabled { - let cacheDirectories = [self.databaseCacheDir?.appending("ManifestLoading"), moduleCachePath].compactMap{ $0 } + let cacheDirectories = [self.databaseCacheDir?.appending("ManifestLoading"), moduleCachePath].compactMap { $0 } let strictness: Sandbox.Strictness = toolsVersion < .v5_3 ? .manifest_pre_53 : .default do { runCmd = try Sandbox.apply(command: runCmd, fileSystem: localFileSystem, strictness: strictness, writableDirectories: cacheDirectories) } catch { - throw error // Re-throw sandbox errors + throw error // Re-throw sandbox errors } } @@ -899,8 +901,8 @@ public final class ManifestLoader: ManifestLoaderProtocol { var environment = Environment.current #if os(Windows) - let windowsPathComponent = runtimePath.pathString.replacing("/", with: "\\") - environment.prependPath(key: .path, value: windowsPathComponent) + let windowsPathComponent = runtimePath.pathString.replacing("/", with: "\\") + environment.prependPath(key: .path, value: windowsPathComponent) #endif let runResult: AsyncProcessResult @@ -919,7 +921,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { duration: evaluationStart.distance(to: .now()) ) } - throw error // Re-throw process errors + throw error // Re-throw process errors } delegateQueue?.async { [delegate = self.delegate] in @@ -933,9 +935,9 @@ public final class ManifestLoader: ManifestLoaderProtocol { // Return now if there was a runtime error. if runResult.exitStatus != .terminated(code: 0) { - // The runtime output is the error - evaluationResult.errorOutput = evaluationResult.compilerOutput - return evaluationResult // Return the result containing the error output + // The runtime output is the error + evaluationResult.errorOutput = evaluationResult.compilerOutput + return evaluationResult // Return the result containing the error output } // Read the JSON output that was emitted by libPackageDescription. @@ -961,11 +963,11 @@ public final class ManifestLoader: ManifestLoaderProtocol { } else { cmd += ["-I", modulesPath.pathString] } - #if os(macOS) - if let sdkRoot = toolchain.sdkRootPath { - cmd += ["-sdk", sdkRoot.pathString] - } - #endif + #if os(macOS) + if let sdkRoot = toolchain.sdkRootPath { + cmd += ["-sdk", sdkRoot.pathString] + } + #endif cmd += ["-package-description-version", toolsVersion.description] return cmd } @@ -1022,14 +1024,15 @@ extension ManifestLoader { let swiftpmVersion: String let sha256Checksum: String - init (packageIdentity: PackageIdentity, - packageLocation: String, - manifestPath: AbsolutePath, - toolsVersion: ToolsVersion, - env: Environment, - swiftpmVersion: String, - extraManifestFlags: [String], - fileSystem: FileSystem + init( + packageIdentity: PackageIdentity, + packageLocation: String, + manifestPath: AbsolutePath, + toolsVersion: ToolsVersion, + env: Environment, + swiftpmVersion: String, + extraManifestFlags: [String], + fileSystem: FileSystem ) throws { let manifestContents = try fileSystem.readFileContents(manifestPath).contents let sha256Checksum = try Self.computeSHA256Checksum( diff --git a/Sources/PackageLoading/ManifestSignatureParser.swift b/Sources/PackageLoading/ManifestSignatureParser.swift index a72b65bbab1..e7837603456 100644 --- a/Sources/PackageLoading/ManifestSignatureParser.swift +++ b/Sources/PackageLoading/ManifestSignatureParser.swift @@ -67,9 +67,11 @@ public enum ManifestSignatureParser { private static func split(_ manifest: String) -> ManifestComponents { // The signature, if any, is the last line in the manifest. let endIndexOfSignatureLine = manifest.lastIndex(where: { !$0.isWhitespace }) ?? manifest.endIndex - let endIndexOfManifestContents = manifest[.. do { entries = try Set(fileSystem.getDirectoryContents(publicHeadersDir).map({ publicHeadersDir.appending(component: $0) })) - } - catch { + } catch { // This might fail because of a file system error, etc. diagnosticsEmitter.emit(.inaccessiblePublicHeadersDirectory(targetName: targetName, publicHeadersDir: publicHeadersDir, fileSystemError: error)) return .none @@ -142,7 +141,7 @@ public struct ModuleMapGenerator { if fileSystem.isFile(nestedUmbrellaHeader) { // In this case, 'PublicHeadersDir' is expected to contain no subdirectories other than 'ModuleName'. if directories.count != 1 { - diagnosticsEmitter.emit(.umbrellaHeaderParentDirHasSiblingDirectories(targetName: targetName, umbrellaHeader: nestedUmbrellaHeader, siblingDirs: directories.filter{ $0.basename != moduleName })) + diagnosticsEmitter.emit(.umbrellaHeaderParentDirHasSiblingDirectories(targetName: targetName, umbrellaHeader: nestedUmbrellaHeader, siblingDirs: directories.filter { $0.basename != moduleName })) return .none } // In this case, 'PublicHeadersDir' is also expected to contain no header files. @@ -197,7 +196,6 @@ public struct ModuleMapGenerator { } } - /// A type of module map to generate. public enum GeneratedModuleMapType { case umbrellaHeader(Basics.AbsolutePath) diff --git a/Sources/PackageLoading/PackageBuilder.swift b/Sources/PackageLoading/PackageBuilder.swift index 77169042aa0..38d67878f25 100644 --- a/Sources/PackageLoading/PackageBuilder.swift +++ b/Sources/PackageLoading/PackageBuilder.swift @@ -99,7 +99,7 @@ public enum ModuleError: Swift.Error { package: PackageIdentity, trait: String ) - + case disablingDefaultTraitsOnEmptyTraits( parentPackage: PackageIdentity, packageName: String @@ -129,17 +129,13 @@ extension ModuleError: CustomStringConvertible { case .invalidManifestConfig(let package, let message): return "configuration of package '\(package)' is invalid; \(message)" case .cycleDetected(let cycle): - return "cyclic dependency declaration found: " + - (cycle.path + cycle.cycle).joined(separator: " -> ") + - " -> " + cycle.cycle[0] + return "cyclic dependency declaration found: " + (cycle.path + cycle.cycle).joined(separator: " -> ") + " -> " + cycle.cycle[0] case .invalidPublicHeadersDirectory(let name): return "public headers (\"include\") directory path for '\(name)' is invalid or not contained in the target" case .overlappingSources(let target, let sources): - return "target '\(target)' has overlapping sources: " + - sources.map(\.description).joined(separator: ", ") + return "target '\(target)' has overlapping sources: " + sources.map(\.description).joined(separator: ", ") case .multipleTestEntryPointFilesFound(let package, let files): - return "package '\(package)' has multiple test entry point files: " + - files.map(\.description).sorted().joined(separator: ", ") + return "package '\(package)' has multiple test entry point files: " + files.map(\.description).sorted().joined(separator: ", ") case .incompatibleToolsVersions(let package, let required, let current): if required.isEmpty { return "package '\(package)' supported Swift language versions is empty" @@ -165,31 +161,31 @@ extension ModuleError: CustomStringConvertible { targetsDescription += " and \(targets.count - 3) others" } return """ - multiple similar targets \(targetsDescription) appear in package '\(package)' and '\(otherPackage)', \ - this may indicate that the two packages are the same and can be de-duplicated by using mirrors. \ - if they are not duplicate consider using the `moduleAliases` parameter in manifest to provide unique names - """ + multiple similar targets \(targetsDescription) appear in package '\(package)' and '\(otherPackage)', \ + this may indicate that the two packages are the same and can be de-duplicated by using mirrors. \ + if they are not duplicate consider using the `moduleAliases` parameter in manifest to provide unique names + """ case .duplicateModulesScmAndRegistry(let registryPackage, let scmPackage, let targets): var targetsDescription = "'\(targets.sorted().prefix(3).joined(separator: "', '"))'" if targets.count > 3 { targetsDescription += " and \(targets.count - 3) others" } return """ - multiple similar targets \(targetsDescription) appear in registry package '\( + multiple similar targets \(targetsDescription) appear in registry package '\( registryPackage - )' and source control package '\(scmPackage)', \ - this may indicate that the two packages are the same and can be de-duplicated \ - by activating the automatic source-control to registry replacement, or by using mirrors. \ - if they are not duplicate consider using the `moduleAliases` parameter in manifest to provide unique names - """ + )' and source control package '\(scmPackage)', \ + this may indicate that the two packages are the same and can be de-duplicated \ + by activating the automatic source-control to registry replacement, or by using mirrors. \ + if they are not duplicate consider using the `moduleAliases` parameter in manifest to provide unique names + """ case .invalidTrait(let package, let trait): return """ - Trait '"\(trait)"' is not declared by package '\(package)'. - """ + Trait '"\(trait)"' is not declared by package '\(package)'. + """ case .disablingDefaultTraitsOnEmptyTraits(let parentPackage, let packageName): return """ - Disabled default traits by package '\(parentPackage)' on package '\(packageName)' that declares no traits. This is prohibited to allow packages to adopt traits initially without causing an API break. - """ + Disabled default traits by package '\(parentPackage)' on package '\(packageName)' that declares no traits. This is prohibited to allow packages to adopt traits initially without causing an API break. + """ } } } @@ -481,7 +477,7 @@ public final class PackageBuilder { private func isValidSource(_ path: AbsolutePath) -> Bool { // Ignore files which don't match the expected extensions. guard let ext = path.extension, - SupportedLanguageExtension.validExtensions(toolsVersion: self.manifest.toolsVersion).contains(ext) + SupportedLanguageExtension.validExtensions(toolsVersion: self.manifest.toolsVersion).contains(ext) else { return false } @@ -545,12 +541,12 @@ public final class PackageBuilder { // it's a system library target. return [ SystemLibraryModule( - name: self.manifest.displayName, // FIXME: use identity instead? + name: self.manifest.displayName, // FIXME: use identity instead? path: self.packagePath, isImplicit: true, pkgConfig: self.manifest.pkgConfig, providers: self.manifest.providers - ), + ) ] } @@ -558,13 +554,15 @@ public final class PackageBuilder { // system target specific configuration. guard self.manifest.pkgConfig == nil else { throw ModuleError.invalidManifestConfig( - self.identity.description, "the 'pkgConfig' property can only be used with a System Module Package" + self.identity.description, + "the 'pkgConfig' property can only be used with a System Module Package" ) } guard self.manifest.providers == nil else { throw ModuleError.invalidManifestConfig( - self.identity.description, "the 'providers' property can only be used with a System Module Package" + self.identity.description, + "the 'providers' property can only be used with a System Module Package" ) } @@ -575,17 +573,20 @@ public final class PackageBuilder { private func findPredefinedTargetDirectory() -> (targetDir: String, testTargetDir: String, pluginTargetDir: String) { - let targetDir = PackageBuilder.predefinedSourceDirectories.first(where: { - self.fileSystem.isDirectory(self.packagePath.appending(component: $0)) - }) ?? PackageBuilder.predefinedSourceDirectories[0] + let targetDir = + PackageBuilder.predefinedSourceDirectories.first(where: { + self.fileSystem.isDirectory(self.packagePath.appending(component: $0)) + }) ?? PackageBuilder.predefinedSourceDirectories[0] - let testTargetDir = PackageBuilder.predefinedTestDirectories.first(where: { - self.fileSystem.isDirectory(self.packagePath.appending(component: $0)) - }) ?? PackageBuilder.predefinedTestDirectories[0] + let testTargetDir = + PackageBuilder.predefinedTestDirectories.first(where: { + self.fileSystem.isDirectory(self.packagePath.appending(component: $0)) + }) ?? PackageBuilder.predefinedTestDirectories[0] - let pluginTargetDir = PackageBuilder.predefinedPluginDirectories.first(where: { - self.fileSystem.isDirectory(self.packagePath.appending(component: $0)) - }) ?? PackageBuilder.predefinedPluginDirectories[0] + let pluginTargetDir = + PackageBuilder.predefinedPluginDirectories.first(where: { + self.fileSystem.isDirectory(self.packagePath.appending(component: $0)) + }) ?? PackageBuilder.predefinedPluginDirectories[0] return (targetDir, testTargetDir, pluginTargetDir) } @@ -615,7 +616,7 @@ public final class PackageBuilder { throw ModuleError.artifactNotFound(moduleName: target.name, expectedArtifactName: target.name) } return artifact.path - } else if let subpath = target.path { // If there is a custom path defined, use that. + } else if let subpath = target.path { // If there is a custom path defined, use that. if subpath == "" || subpath == "." { return self.packagePath } @@ -637,14 +638,15 @@ public final class PackageBuilder { } // Check if target is present in the predefined directory. - let predefinedDir: PredefinedTargetDirectory = switch target.type { - case .test: - predefinedTestTargetDirectory - case .plugin: - predefinedPluginTargetDirectory - default: - predefinedTargetDirectory - } + let predefinedDir: PredefinedTargetDirectory = + switch target.type { + case .test: + predefinedTestTargetDirectory + case .plugin: + predefinedPluginTargetDirectory + default: + predefinedTargetDirectory + } let path = predefinedDir.path.appending(component: target.name) // Return the path if the predefined directory contains it. @@ -694,7 +696,8 @@ public final class PackageBuilder { // Snippets: depend on all available library targets in the package. // TODO: Do we need to filter out targets that aren't available on the host platform? let productTargets = Set(manifest.products.flatMap(\.targets)) - let snippetDependencies = targets + let snippetDependencies = + targets .filter { $0.type == .library && productTargets.contains($0.name) } .map { Module.Dependency.module($0, conditions: []) } snippetTargets = try createSnippetModules(dependencies: snippetDependencies) @@ -764,7 +767,7 @@ public final class PackageBuilder { if let potentialModule = potentialModuleMap[name] { potentialModule } else if let targetName = pluginTargetName(for: name), - let potentialModule = potentialModuleMap[targetName] + let potentialModule = potentialModuleMap[targetName] { potentialModule } else { @@ -796,62 +799,64 @@ public final class PackageBuilder { let manifestTarget = manifest.targetMap[potentialModule.name] // Get the dependencies of this target. - let dependencies: [Module.Dependency] = try manifestTarget.map { target in - try target.dependencies.compactMap { dependency -> Module.Dependency? in - // We don't create an object for target dependencies that aren't enabled. - guard try self.manifest.isTargetDependencyEnabled(target: target.name, dependency, enabledTraits: self.enabledTraits) else { - return nil - } - switch dependency { - case .target(let name, let condition): - // We don't create an object for targets which have no sources. - if emptyModules.contains(name) { return nil } - guard let target = targets[name] else { return nil } - return .module(target, conditions: buildConditions(from: condition)) - - case .product(let name, let package, let moduleAliases, let condition): - try validateModuleAliases(moduleAliases) - return .product( - .init(name: name, package: package, moduleAliases: moduleAliases), - conditions: buildConditions(from: condition) - ) - case .byName(let name, let condition): - // We don't create an object for targets which have no sources. - if emptyModules.contains(name) { return nil } - if let target = targets[name] { + let dependencies: [Module.Dependency] = + try manifestTarget.map { target in + try target.dependencies.compactMap { dependency -> Module.Dependency? in + // We don't create an object for target dependencies that aren't enabled. + guard try self.manifest.isTargetDependencyEnabled(target: target.name, dependency, enabledTraits: self.enabledTraits) else { + return nil + } + switch dependency { + case .target(let name, let condition): + // We don't create an object for targets which have no sources. + if emptyModules.contains(name) { return nil } + guard let target = targets[name] else { return nil } return .module(target, conditions: buildConditions(from: condition)) - } else if potentialModuleMap[name] == nil { + + case .product(let name, let package, let moduleAliases, let condition): + try validateModuleAliases(moduleAliases) return .product( - .init(name: name, package: nil), + .init(name: name, package: package, moduleAliases: moduleAliases), conditions: buildConditions(from: condition) ) - } else { - return nil + case .byName(let name, let condition): + // We don't create an object for targets which have no sources. + if emptyModules.contains(name) { return nil } + if let target = targets[name] { + return .module(target, conditions: buildConditions(from: condition)) + } else if potentialModuleMap[name] == nil { + return .product( + .init(name: name, package: nil), + conditions: buildConditions(from: condition) + ) + } else { + return nil + } } } - } - } ?? [] + } ?? [] // Get dependencies from the plugin usages of this target. - let pluginUsages: [Module.PluginUsage] = manifestTarget?.pluginUsages.map { - $0.compactMap { usage in - switch usage { - case .plugin(let name, let package): - if let package { - return .product(Module.ProductReference(name: name, package: package), conditions: []) - } else { - if let target = targets[name] { - return .module(target, conditions: []) - } else if let targetName = pluginTargetName(for: name), let target = targets[targetName] { - return .module(target, conditions: []) + let pluginUsages: [Module.PluginUsage] = + manifestTarget?.pluginUsages.map { + $0.compactMap { usage in + switch usage { + case .plugin(let name, let package): + if let package { + return .product(Module.ProductReference(name: name, package: package), conditions: []) } else { - self.observabilityScope.emit(.pluginNotFound(name: name)) - return nil + if let target = targets[name] { + return .module(target, conditions: []) + } else if let targetName = pluginTargetName(for: name), let target = targets[targetName] { + return .module(target, conditions: []) + } else { + self.observabilityScope.emit(.pluginNotFound(name: name)) + return nil + } } } } - } - } ?? [] + } ?? [] // Create the target, adding the inferred dependencies from plugin usages to the declared dependencies. let target = try createTarget( @@ -864,15 +869,18 @@ public final class PackageBuilder { targets[createdTarget.name] = createdTarget } else { emptyModules.insert(potentialModule.name) - self.observabilityScope.emit(.targetHasNoSources( - name: potentialModule.name, - type: potentialModule.type, - shouldSuggestRelaxedSourceDir: manifest - .shouldSuggestRelaxedSourceDir( - type: potentialModule - .type - ) - )) + self.observabilityScope.emit( + .targetHasNoSources( + name: potentialModule.name, + type: potentialModule.type, + shouldSuggestRelaxedSourceDir: + manifest + .shouldSuggestRelaxedSourceDir( + type: potentialModule + .type + ) + ) + ) } } @@ -894,10 +902,7 @@ public final class PackageBuilder { private func validateModuleAliases(_ aliases: [String: String]?) throws { guard let aliases else { return } for (aliasKey, aliasValue) in aliases { - if !aliasKey.isValidIdentifier || - !aliasValue.isValidIdentifier || - aliasKey == aliasValue - { + if !aliasKey.isValidIdentifier || !aliasValue.isValidIdentifier || aliasKey == aliasValue { throw ModuleError.invalidModuleAlias(originalName: aliasKey, newName: aliasValue) } } @@ -920,7 +925,8 @@ public final class PackageBuilder { return SystemLibraryModule( name: potentialModule.name, - path: potentialModule.path, isImplicit: false, + path: potentialModule.path, + isImplicit: false, pkgConfig: manifestTarget.pkgConfig, providers: manifestTarget.providers ) @@ -949,21 +955,25 @@ public final class PackageBuilder { } let dupTargetNames = dependencies.compactMap { $0.module?.name }.spm_findDuplicates() for dupTargetName in dupTargetNames { - self.observabilityScope.emit(.duplicateTargetDependency( - dependency: dupTargetName, - target: potentialModule.name, - package: self.identity.description - )) + self.observabilityScope.emit( + .duplicateTargetDependency( + dependency: dupTargetName, + target: potentialModule.name, + package: self.identity.description + ) + ) } } else { dependencies.filter { $0.product?.moduleAliases == nil }.spm_findDuplicateElements(by: \.nameAndType) .map(\.[0].name).forEach { self.observabilityScope - .emit(.duplicateTargetDependency( - dependency: $0, - target: potentialModule.name, - package: self.identity.description - )) + .emit( + .duplicateTargetDependency( + dependency: $0, + target: potentialModule.name, + package: self.identity.description + ) + ) } } @@ -972,10 +982,12 @@ public final class PackageBuilder { if !potentialModule.isTest { for dependency in dependencies { if let depTarget = dependency.module, depTarget.type == .test { - self.observabilityScope.emit(.invalidDependencyOnTestTarget( - dependency: dependency, - targetName: potentialModule.name - )) + self.observabilityScope.emit( + .invalidDependencyOnTestTarget( + dependency: dependency, + targetName: potentialModule.name + ) + ) } } } @@ -1053,8 +1065,9 @@ public final class PackageBuilder { moduleKind = .macro default: moduleKind = sources.computeModuleKind() - if moduleKind == .executable && self.manifest.toolsVersion >= .v5_4 && self - .warnAboutImplicitExecutableTargets + if moduleKind == .executable && self.manifest.toolsVersion >= .v5_4 + && self + .warnAboutImplicitExecutableTargets { self.observabilityScope .emit( @@ -1155,7 +1168,7 @@ public final class PackageBuilder { // The setting is currently not enabled so we should skip it continue } - + let decl: BuildSettings.Declaration let values: [String] @@ -1220,8 +1233,7 @@ public final class PackageBuilder { } if lang == .Cxx { - values = ["-cxx-interoperability-mode=default"] + - (cxxLanguageStandard.flatMap { ["-Xcc", "-std=\($0)"] } ?? []) + values = ["-cxx-interoperability-mode=default"] + (cxxLanguageStandard.flatMap { ["-Xcc", "-std=\($0)"] } ?? []) } else { values = [] } @@ -1292,20 +1304,22 @@ public final class PackageBuilder { switch setting.tool { case .c: decl = .OTHER_CFLAGS - let flag = switch level { - case .error: "-Werror" - case .warning: "-Wno-error" - } + let flag = + switch level { + case .error: "-Werror" + case .warning: "-Wno-error" + } values = [flag] - + case .cxx: decl = .OTHER_CPLUSPLUSFLAGS - let flag = switch level { - case .error: "-Werror" - case .warning: "-Wno-error" - } + let flag = + switch level { + case .error: "-Werror" + case .warning: "-Wno-error" + } values = [flag] - + case .linker: throw InternalError("linker does not support treatAllWarnings") @@ -1314,10 +1328,11 @@ public final class PackageBuilder { // SWIFT_WARNINGS_AS_ERRORS_GROUPS here. // See https://github.com/swiftlang/swift-build/issues/248 decl = .OTHER_SWIFT_FLAGS - let flag = switch level { - case .error: "-warnings-as-errors" - case .warning: "-no-warnings-as-errors" - } + let flag = + switch level { + case .error: "-warnings-as-errors" + case .warning: "-no-warnings-as-errors" + } values = [flag] } @@ -1325,20 +1340,22 @@ public final class PackageBuilder { switch setting.tool { case .c: decl = .OTHER_CFLAGS - let flag = switch level { - case .error: "-Werror=\(name)" - case .warning: "-Wno-error=\(name)" - } + let flag = + switch level { + case .error: "-Werror=\(name)" + case .warning: "-Wno-error=\(name)" + } values = [flag] - + case .cxx: decl = .OTHER_CPLUSPLUSFLAGS - let flag = switch level { - case .error: "-Werror=\(name)" - case .warning: "-Wno-error=\(name)" - } + let flag = + switch level { + case .error: "-Werror=\(name)" + case .warning: "-Wno-error=\(name)" + } values = [flag] - + case .linker: throw InternalError("linker does not support treatWarning") @@ -1347,10 +1364,11 @@ public final class PackageBuilder { // SWIFT_WARNINGS_AS_ERRORS_GROUPS here. // See https://github.com/swiftlang/swift-build/issues/248 decl = .OTHER_SWIFT_FLAGS - let flag = switch level { - case .error: "-Werror" - case .warning: "-Wwarning" - } + let flag = + switch level { + case .error: "-Werror" + case .warning: "-Wwarning" + } values = [flag, name] } @@ -1412,8 +1430,8 @@ public final class PackageBuilder { if target.type == .macro || target.isMacroTest(in: manifest) { let prebuiltLibraries: [String: PrebuiltLibrary] = target.dependencies.reduce(into: .init()) { guard case let .product(name: name, package: package, moduleAliases: _, condition: _) = $1, - let package = package, - let prebuilt = prebuilts[.plain(package)]?[name] + let package = package, + let prebuilt = prebuilts[.plain(package)]?[name] else { return } @@ -1481,7 +1499,9 @@ public final class PackageBuilder { if versions.isEmpty { throw ModuleError.incompatibleToolsVersions( - package: self.identity.description, required: swiftLanguageVersions, current: .current + package: self.identity.description, + required: swiftLanguageVersions, + current: .current ) } } else { @@ -1500,12 +1520,13 @@ public final class PackageBuilder { // Figure out the swift version from declared list in the manifest. let declaredSwiftVersions = try declaredSwiftVersions() - let computedSwiftVersion: SwiftLanguageVersion = if let declaredSwiftVersion = declaredSwiftVersions.first { - declaredSwiftVersion - } else { - // Otherwise, use the version depending on the manifest version. - self.manifest.toolsVersion.swiftLanguageVersion - } + let computedSwiftVersion: SwiftLanguageVersion = + if let declaredSwiftVersion = declaredSwiftVersions.first { + declaredSwiftVersion + } else { + // Otherwise, use the version depending on the manifest version. + self.manifest.toolsVersion.swiftLanguageVersion + } self.swiftVersionCache = computedSwiftVersion return computedSwiftVersion } @@ -1570,7 +1591,8 @@ public final class PackageBuilder { // It is an error if there are multiple linux main files. if testEntryPointFiles.count > 1 { throw ModuleError.multipleTestEntryPointFilesFound( - package: self.identity.description, files: testEntryPointFiles.map { $0 } + package: self.identity.description, + files: testEntryPointFiles.map { $0 } ) } return testEntryPointFiles.first @@ -1592,12 +1614,12 @@ public final class PackageBuilder { let testModules = modules.filter { module in guard module.type == .test else { return false } #if os(Linux) - // FIXME: Ignore C language test targets on linux for now. - if module is ClangModule { - self.observabilityScope - .emit(.unsupportedCTestTarget(package: self.identity.description, target: module.name)) - return false - } + // FIXME: Ignore C language test targets on linux for now. + if module is ClangModule { + self.observabilityScope + .emit(.unsupportedCTestTarget(package: self.identity.description, target: module.name)) + return false + } #endif return true } @@ -1650,12 +1672,13 @@ public final class PackageBuilder { // First add explicit products. - let filteredProducts: [ProductDescription] = switch self.productFilter { - case .everything: - self.manifest.products - case .specific(let set): - self.manifest.products.filter { set.contains($0.name) } - } + let filteredProducts: [ProductDescription] = + switch self.productFilter { + case .everything: + self.manifest.products + case .specific(let set): + self.manifest.products.filter { set.contains($0.name) } + } for product in filteredProducts { if product.name.isEmpty { throw Product.Error.emptyName @@ -1697,14 +1720,16 @@ public final class PackageBuilder { // Compute the list of targets which are being used in an // executable product so we don't create implicit executables // for them. - let explicitProductsModules = Set(self.manifest.products.flatMap { product -> [String] in - switch product.type { - case .library, .plugin, .test, .macro: - return [] - case .executable, .snippet: - return product.targets + let explicitProductsModules = Set( + self.manifest.products.flatMap { product -> [String] in + switch product.type { + case .library, .plugin, .test, .macro: + return [] + case .executable, .snippet: + return product.targets + } } - }) + ) let productMap = products.reduce(into: [String: Product]()) { partial, iterator in partial[iterator.key] = iterator.item @@ -1782,21 +1807,25 @@ public final class PackageBuilder { private func validateLibraryProduct(_ product: ProductDescription, with targets: [Module]) -> Bool { let pluginTargets = targets.filter { $0.type == .plugin } guard pluginTargets.isEmpty else { - self.observabilityScope.emit(.nonPluginProductWithPluginTargets( - product: product.name, - type: product.type, - pluginTargets: pluginTargets.map(\.name) - )) + self.observabilityScope.emit( + .nonPluginProductWithPluginTargets( + product: product.name, + type: product.type, + pluginTargets: pluginTargets.map(\.name) + ) + ) return false } if self.manifest.toolsVersion >= .v5_7 { let executableTargets = targets.filter { $0.type == .executable } guard executableTargets.isEmpty else { self.observabilityScope - .emit(.libraryProductWithExecutableTarget( - product: product.name, - executableTargets: executableTargets.map(\.name) - )) + .emit( + .libraryProductWithExecutableTarget( + product: product.name, + executableTargets: executableTargets.map(\.name) + ) + ) return false } } @@ -1820,11 +1849,13 @@ public final class PackageBuilder { } let pluginTargets = targets.filter { $0.type == .plugin } guard pluginTargets.isEmpty else { - self.observabilityScope.emit(.nonPluginProductWithPluginTargets( - product: product.name, - type: product.type, - pluginTargets: pluginTargets.map(\.name) - )) + self.observabilityScope.emit( + .nonPluginProductWithPluginTargets( + product: product.name, + type: product.type, + pluginTargets: pluginTargets.map(\.name) + ) + ) return false } return true @@ -1834,10 +1865,12 @@ public final class PackageBuilder { let nonPluginTargets = targets.filter { $0.type != .plugin } guard nonPluginTargets.isEmpty else { self.observabilityScope - .emit(.pluginProductWithNonPluginTargets( - product: product.name, - otherTargets: nonPluginTargets.map(\.name) - )) + .emit( + .pluginProductWithNonPluginTargets( + product: product.name, + otherTargets: nonPluginTargets.map(\.name) + ) + ) return false } guard !targets.isEmpty else { @@ -1897,14 +1930,15 @@ extension Manifest { /// Returns the names of all the visible modules in the manifest. fileprivate func visibleModuleNames(for productFilter: ProductFilter) -> Set { let names = targetsRequired(for: productFilter).flatMap { target in - [target.name] + target.dependencies.compactMap { - switch $0 { - case .target(let name, _): - name - case .byName, .product: - nil + [target.name] + + target.dependencies.compactMap { + switch $0 { + case .target(let name, _): + name + case .byName, .product: + nil + } } - } } return Set(names) } @@ -1973,7 +2007,8 @@ extension PackageBuilder { let targetDescription = try TargetDescription( name: name, - dependencies: dependencies + dependencies: + dependencies .map { TargetDescription.Dependency.target(name: $0.name) }, diff --git a/Sources/PackageLoading/PkgConfig.swift b/Sources/PackageLoading/PkgConfig.swift index 21e0c514e9e..489037b9336 100644 --- a/Sources/PackageLoading/PkgConfig.swift +++ b/Sources/PackageLoading/PkgConfig.swift @@ -133,9 +133,9 @@ public struct PkgConfig { get throws { if let configPath = Environment.current["PKG_CONFIG_PATH"] { #if os(Windows) - return try configPath.split(separator: ";").map({ try AbsolutePath(validating: String($0)) }) + return try configPath.split(separator: ";").map({ try AbsolutePath(validating: String($0)) }) #else - return try configPath.split(separator: ":").map({ try AbsolutePath(validating: String($0)) }) + return try configPath.split(separator: ":").map({ try AbsolutePath(validating: String($0)) }) #endif } return [] @@ -154,7 +154,6 @@ extension PkgConfig { } } - /// Parser for the `pkg-config` `.pc` file format. /// /// See: https://www.freedesktop.org/wiki/Software/pkg-config/ @@ -210,7 +209,7 @@ internal struct PkgConfigParser { // Only trim if sysroot is defined with a meaningful value guard let sysrootDir, sysrootDir != "/" else { - return value + return value } // Only trim absolute paths starting with sysroot @@ -338,7 +337,7 @@ internal struct PkgConfigParser { // Encountered a separator, use the token. if separators.contains(String(char)) { // If next character is a space skip. - if let peeked = peek(idx: idx+1), peeked == " " { continue } + if let peeked = peek(idx: idx + 1), peeked == " " { continue } // Append to array of tokens and reset token variable. tokens.append(token) token = "" @@ -358,10 +357,12 @@ internal struct PkgConfigParser { if operators.contains(arg) { // We should have a version number next, skip. guard it.next() != nil else { - throw PkgConfigError.parsingError(""" + throw PkgConfigError.parsingError( + """ Expected version number after \(deps.last.debugDescription) \(arg) in \"\(depString)\" in \ \(pcFile) - """) + """ + ) } } else if !arg.isEmpty { // Otherwise it is a dependency. @@ -381,10 +382,11 @@ internal struct PkgConfigParser { // Returns variable name, start index and end index of a variable in a string if present. // We make sure it of form ${name} otherwise it is not a variable. func findVariable(_ fragment: String) - -> (name: String, startIndex: String.Index, endIndex: String.Index)? { + -> (name: String, startIndex: String.Index, endIndex: String.Index)? + { guard let dollar = fragment.firstIndex(of: "$"), - dollar != fragment.endIndex && fragment[fragment.index(after: dollar)] == "{", - let variableEndIndex = fragment.firstIndex(of: "}") + dollar != fragment.endIndex && fragment[fragment.index(after: dollar)] == "{", + let variableEndIndex = fragment.firstIndex(of: "}") else { return nil } return (String(fragment[fragment.index(dollar, offsetBy: 2).. Bool { - (try? Basics.localFileSystem.isFile(AbsolutePath(validating: "/system/bin/toolchain"))) ?? false || - (try? Basics.localFileSystem.isFile(AbsolutePath(validating: "/system/bin/toybox"))) ?? false + (try? Basics.localFileSystem.isFile(AbsolutePath(validating: "/system/bin/toolchain"))) ?? false || (try? Basics.localFileSystem.isFile(AbsolutePath(validating: "/system/bin/toybox"))) ?? false } public enum Platform: Equatable, Sendable { @@ -38,21 +37,21 @@ public enum Platform: Equatable, Sendable { extension Platform { public static let current: Platform? = { #if os(Windows) - return .windows + return .windows #else - switch try? AsyncProcess.checkNonZeroExit(args: "uname") - .trimmingCharacters(in: .whitespacesAndNewlines) - .lowercased() - { - case "darwin"?: - return .darwin - case "freebsd"?: - return .freebsd - case "linux"?: - return Platform.findCurrentPlatformLinux(Basics.localFileSystem) - default: - return nil - } + switch try? AsyncProcess.checkNonZeroExit(args: "uname") + .trimmingCharacters(in: .whitespacesAndNewlines) + .lowercased() + { + case "darwin"?: + return .darwin + case "freebsd"?: + return .freebsd + case "linux"?: + return Platform.findCurrentPlatformLinux(Basics.localFileSystem) + default: + return nil + } #endif }() @@ -61,16 +60,10 @@ extension Platform { if try fileSystem.isFile(AbsolutePath(validating: "/etc/debian_version")) { return .linux(.debian) } - if try fileSystem.isFile(AbsolutePath(validating: "/system/bin/toolbox")) || - fileSystem.isFile(AbsolutePath(validating: "/system/bin/toybox")) - { + if try fileSystem.isFile(AbsolutePath(validating: "/system/bin/toolbox")) || fileSystem.isFile(AbsolutePath(validating: "/system/bin/toybox")) { return .android } - if try fileSystem.isFile(AbsolutePath(validating: "/etc/redhat-release")) || - fileSystem.isFile(AbsolutePath(validating: "/etc/centos-release")) || - fileSystem.isFile(AbsolutePath(validating: "/etc/fedora-release")) || - Platform.isAmazonLinux2(fileSystem) - { + if try fileSystem.isFile(AbsolutePath(validating: "/etc/redhat-release")) || fileSystem.isFile(AbsolutePath(validating: "/etc/centos-release")) || fileSystem.isFile(AbsolutePath(validating: "/etc/fedora-release")) || Platform.isAmazonLinux2(fileSystem) { return .linux(.fedora) } } catch {} diff --git a/Sources/PackageLoading/Target+PkgConfig.swift b/Sources/PackageLoading/Target+PkgConfig.swift index 49b6fc30be7..387893a93f5 100644 --- a/Sources/PackageLoading/Target+PkgConfig.swift +++ b/Sources/PackageLoading/Target+PkgConfig.swift @@ -40,8 +40,8 @@ public struct PkgConfigResult { /// If the pc file was not found. public var couldNotFindConfigFile: Bool { switch error { - case PkgConfigError.couldNotFindConfigFile?: return true - default: return false + case PkgConfigError.couldNotFindConfigFile?: return true + default: return false } } @@ -252,11 +252,11 @@ public func allowlist( continue } - // Warning suppression flag has no arguments and is not suffixed. - guard !flag.hasPrefix("-w") || flag == "-w" else { - disallowed += [flag] - continue - } + // Warning suppression flag has no arguments and is not suffixed. + guard !flag.hasPrefix("-w") || flag == "-w" else { + disallowed += [flag] + continue + } // If the flag and its value are separated, skip next flag. if flag == filter && flag != "-w" { diff --git a/Sources/PackageLoading/TargetSourcesBuilder.swift b/Sources/PackageLoading/TargetSourcesBuilder.swift index 87f235ed3a0..0bf6fae4028 100644 --- a/Sources/PackageLoading/TargetSourcesBuilder.swift +++ b/Sources/PackageLoading/TargetSourcesBuilder.swift @@ -84,9 +84,12 @@ public struct TargetSourcesBuilder { let excludedPaths = target.exclude.compactMap { try? AbsolutePath(validating: $0, relativeTo: path) } self.excludedPaths = Set(excludedPaths) self.opaqueDirectoriesExtensions = FileRuleDescription.opaqueDirectoriesExtensions.union( - additionalFileRules.reduce(into: Set(), { partial, item in - partial.formUnion(item.fileTypes) - }) + additionalFileRules.reduce( + into: Set(), + { partial, item in + partial.formUnion(item.fileTypes) + } + ) ) self.fileSystem = fileSystem @@ -113,9 +116,10 @@ public struct TargetSourcesBuilder { self.declaredSources = declaredSources - self.declaredResources = (try? target.resources.map { - (path: try AbsolutePath(validating: $0.path, relativeTo: path), rule: $0.rule) - }) ?? [] + self.declaredResources = + (try? target.resources.map { + (path: try AbsolutePath(validating: $0.path, relativeTo: path), rule: $0.rule) + }) ?? [] self.excludedPaths.forEach { exclude in if let message = validTargetPath(at: exclude), self.packageKind.emitAuthorWarnings { @@ -131,9 +135,9 @@ public struct TargetSourcesBuilder { } } - #if DEBUG - validateRules(self.rules) - #endif + #if DEBUG + validateRules(self.rules) + #endif } private static func rules(additionalFileRules: [FileRuleDescription], toolsVersion: ToolsVersion) -> [FileRuleDescription] { @@ -229,17 +233,19 @@ public struct TargetSourcesBuilder { } /// Compute the rule for the given path. - private static func computeRule(for path: Basics.AbsolutePath, - toolsVersion: ToolsVersion, - additionalFileRules: [FileRuleDescription], - observabilityScope: ObservabilityScope) -> FileRuleDescription.Rule { + private static func computeRule( + for path: Basics.AbsolutePath, + toolsVersion: ToolsVersion, + additionalFileRules: [FileRuleDescription], + observabilityScope: ObservabilityScope + ) -> FileRuleDescription.Rule { let rules = Self.rules(additionalFileRules: additionalFileRules, toolsVersion: toolsVersion) // For now, we are not passing in any declared resources or sources here and instead handle any generated files automatically at the callsite. Eventually, we will want the ability to declare opinions for generated files in the manifest as well. return Self.computeRule(for: path, toolsVersion: toolsVersion, rules: rules, declaredResources: [], declaredSources: nil, observabilityScope: observabilityScope) } private static func computeRule( - for path: Basics.AbsolutePath, + for path: Basics.AbsolutePath, toolsVersion: ToolsVersion, rules: [FileRuleDescription], declaredResources: [(path: Basics.AbsolutePath, rule: TargetDescription.Resource.Rule)], @@ -268,21 +274,23 @@ public struct TargetSourcesBuilder { observabilityScope.emit(error: "duplicate rule found for file at '\(path)'") } - // Check for header files as they're allowed to be mixed with sources. - if let ext = path.extension, - FileRuleDescription.header.fileTypes.contains(ext) { - matchedRule = .header - } else if toolsVersion >= .v5_3 { - matchedRule = .compile - } else if let ext = path.extension, - SupportedLanguageExtension.validExtensions(toolsVersion: toolsVersion).contains(ext) { - matchedRule = .compile - } - // The source file might have been declared twice so - // exit on first match. - // FIXME: We should emitting warnings for duplicate// declarations. + // Check for header files as they're allowed to be mixed with sources. + if let ext = path.extension, + FileRuleDescription.header.fileTypes.contains(ext) + { + matchedRule = .header + } else if toolsVersion >= .v5_3 { + matchedRule = .compile + } else if let ext = path.extension, + SupportedLanguageExtension.validExtensions(toolsVersion: toolsVersion).contains(ext) + { + matchedRule = .compile } + // The source file might have been declared twice so + // exit on first match. + // FIXME: We should emitting warnings for duplicate// declarations. } + } // We haven't found a rule using that's explicitly declared in the manifest // so try doing an automatic match. @@ -305,7 +313,7 @@ public struct TargetSourcesBuilder { return matchedRule } - + private static func isDescendantOfOrEqualToAny(_ path: Basics.AbsolutePath, _ ancestorPaths: OrderedCollections.OrderedSet) -> Bool { var currentPath = path while true { @@ -338,7 +346,7 @@ public struct TargetSourcesBuilder { }() let explicitLocalization: String? = { - switch rule { + switch rule { case .processResource(localization: .default): return defaultLocalization ?? "en" case .processResource(localization: .base): @@ -380,10 +388,12 @@ public struct TargetSourcesBuilder { } private func diagnoseCopyConflictsWithLocalizationDirectories(in resources: [Resource]) { - let localizationDirectories = Set(resources - .lazy - .compactMap({ $0.localization }) - .map({ "\($0).\(Resource.localizationDirectoryExtension)" })) + let localizationDirectories = Set( + resources + .lazy + .compactMap({ $0.localization }) + .map({ "\($0).\(Resource.localizationDirectoryExtension)" }) + ) for resource in resources where resource.rule == .copy { if localizationDirectories.contains(resource.path.basename.lowercased()) { @@ -407,9 +417,12 @@ public struct TargetSourcesBuilder { private func diagnoseInfoPlistConflicts(in resources: [Resource]) throws { for resource in resources { if try resource.destination == RelativePath(validating: "Info.plist") { - self.observabilityScope.emit(.infoPlistResourceConflict( - path: resource.path.relative(to: targetPath), - targetName: target.name)) + self.observabilityScope.emit( + .infoPlistResourceConflict( + path: resource.path.relative(to: targetPath), + targetName: target.name + ) + ) } } } @@ -486,9 +499,9 @@ public struct TargetSourcesBuilder { // ie, do not include their content, and instead treat the directory itself as the content if toolsVersion >= .v5_6 { if let directoryExtension = path.extension, - self.opaqueDirectoriesExtensions.contains(directoryExtension), - directoryExtension != Resource.localizationDirectoryExtension, - !isDeclaredSource(path) + self.opaqueDirectoriesExtensions.contains(directoryExtension), + directoryExtension != Resource.localizationDirectoryExtension, + !isDeclaredSource(path) { contents.append(path) continue @@ -497,8 +510,8 @@ public struct TargetSourcesBuilder { // maintain the broken behavior prior to fixing it in 5.6 // see rdar://82933763 if let directoryExtension = path.extension, - directoryExtension != Resource.localizationDirectoryExtension, - !isDeclaredSource(path) + directoryExtension != Resource.localizationDirectoryExtension, + !isDeclaredSource(path) { contents.append(path) continue @@ -506,7 +519,7 @@ public struct TargetSourcesBuilder { } // Check if the directory is marked to be copied. - let directoryMarkedToBeCopied = target.resources.contains{ resource in + let directoryMarkedToBeCopied = target.resources.contains { resource in let resourcePath = try? AbsolutePath(validating: resource.path, relativeTo: self.targetPath) if resource.rule == .copy && resourcePath == path { return true @@ -523,9 +536,12 @@ public struct TargetSourcesBuilder { // We found a directory inside a localization directory, which is forbidden. if path.parentDirectory.extension == Resource.localizationDirectoryExtension { let relativePath = path.parentDirectory.relative(to: targetPath) - self.observabilityScope.emit(.localizationDirectoryContainsSubDirectories( - localizationDirectory: relativePath, - targetName: target.name)) + self.observabilityScope.emit( + .localizationDirectoryContainsSubDirectories( + localizationDirectory: relativePath, + targetName: target.name + ) + ) continue } @@ -790,14 +806,17 @@ public struct FileRuleDescription: Sendable { /// List of file directory extensions that should be treated as opaque, non source, directories. public static var opaqueDirectoriesExtensions: Set { let types = Self.xcbuildFileTypes + Self.swiftpmFileTypes - return types.reduce(into: Set(), { partial, item in - partial.formUnion(item.fileTypes) - }) + return types.reduce( + into: Set(), + { partial, item in + partial.formUnion(item.fileTypes) + } + ) } } extension FileRuleDescription.Rule { - init(_ seed: TargetDescription.Resource.Rule) { + init(_ seed: TargetDescription.Resource.Rule) { switch seed { case .process(let localization): self = .processResource(localization: localization) diff --git a/Sources/PackageLoading/ToolsVersionParser.swift b/Sources/PackageLoading/ToolsVersionParser.swift index f38e2e4eb07..f54e3635c51 100644 --- a/Sources/PackageLoading/ToolsVersionParser.swift +++ b/Sources/PackageLoading/ToolsVersionParser.swift @@ -56,9 +56,9 @@ public struct ToolsVersionParser { } do { - return try self.parse(utf8String: manifestContentsDecodedWithUTF8) + return try self.parse(utf8String: manifestContentsDecodedWithUTF8) } catch Error.malformedToolsVersionSpecification(.commentMarker(.isMissing)) { - throw UnsupportedToolsVersion(packageIdentity: .init(path: manifestPath), currentToolsVersion: .current, packageToolsVersion: .v3) + throw UnsupportedToolsVersion(packageIdentity: .init(path: manifestPath), currentToolsVersion: .current, packageToolsVersion: .v3) } } @@ -223,7 +223,7 @@ public struct ToolsVersionParser { /// The position of the first character of the Swift tools version specification line in the manifest. /// /// Because the tools version specification line is the first non-whitespace-only line in the manifest, the position of its first character is also the position of the first non-whitespace character in the manifest. If there is only whitespace in the manifest, then this position is the `endIndex` of the manifest. - let startIndexOfSpecification = manifest.firstIndex(where: { !$0.isWhitespace } ) ?? manifest.endIndex + let startIndexOfSpecification = manifest.firstIndex(where: { !$0.isWhitespace }) ?? manifest.endIndex /// The whitespace at the start of the manifest. /// @@ -245,7 +245,7 @@ public struct ToolsVersionParser { /// The position right past the last character of the Swift tools version specification's comment marker. /// /// This is the same as the position of the first character that is neither `"/"` nor `"*"` in the Swift tools version specification. If no such character exists, then this position is the `endIndex` of the Swift tools version specification. - let endIndexOfCommentMarker = specificationWithIgnoredTrailingContents.firstIndex(where: { $0 != "/" && $0 != "*" } ) ?? specificationWithIgnoredTrailingContents.endIndex + let endIndexOfCommentMarker = specificationWithIgnoredTrailingContents.firstIndex(where: { $0 != "/" && $0 != "*" }) ?? specificationWithIgnoredTrailingContents.endIndex /// The comment marker of the Swift tools version specification. /// @@ -255,7 +255,7 @@ public struct ToolsVersionParser { /// The position right past the last character of the spacing that immediately follows the comment marker. /// /// Because the spacing consists of only horizontal whitespace characters, this position is the same as the first character that's not a horizontal whitespace after `commentMarker`. If no such character exists, then the position is the `endIndex` of the Swift tools version specification line. - let startIndexOfLabel = specificationWithIgnoredTrailingContents[endIndexOfCommentMarker...].firstIndex(where: { !$0.isWhitespace } ) ?? specificationWithIgnoredTrailingContents.endIndex + let startIndexOfLabel = specificationWithIgnoredTrailingContents[endIndexOfCommentMarker...].firstIndex(where: { !$0.isWhitespace }) ?? specificationWithIgnoredTrailingContents.endIndex // ☝️ // Technically, this is looking for the position of the first character that's not a whitespace, BOTH HORIZONTAL AND VERTICAL. However, since all vertical horizontal whitespace characters are also line terminators, and because the Swift tools version specification does not contain any line terminator, we can safely use `Character.isWhitespace` to check if a character is a horizontal whitespace. @@ -325,7 +325,7 @@ public struct ToolsVersionParser { // The optional index can be safely unwrapped, because we know for sure there is a ":" in the substring. 👇 endIndexOfLabel = specificationSnippetFromLabelToLineTerminator.index(after: specificationSnippetFromLabelToLineTerminator.firstIndex(of: ":")!) // Because there is potentially a spacing between the label and the version specifier, we need to skip the whitespace first. - startIndexOfVersionSpecifier = specificationSnippetFromLabelToLineTerminator[endIndexOfLabel...].firstIndex(where: { !$0.isWhitespace } ) ?? specificationSnippetFromLabelToLineTerminator.endIndex + startIndexOfVersionSpecifier = specificationSnippetFromLabelToLineTerminator[endIndexOfLabel...].firstIndex(where: { !$0.isWhitespace }) ?? specificationSnippetFromLabelToLineTerminator.endIndex } else { // FIXME: Use `CharacterSet.decimalDigits` instead? // `Character.isNumber` is true for more than just decimal characters (e.g. ㊅ and 𝟘), but `CharacterSet.contains(_:)` works only on Unicode scalars. @@ -348,7 +348,7 @@ public struct ToolsVersionParser { /// The position of the version specifier's terminator. /// /// The terminator can be either a `";"` or a line terminator. If no such character exists, then this position is the `endIndex` of the Swift tools version specification. - let indexOfVersionSpecifierTerminator = specificationWithIgnoredTrailingContents[startIndexOfVersionSpecifier...].firstIndex(where: { $0 == ";" } ) ?? specificationWithIgnoredTrailingContents.endIndex + let indexOfVersionSpecifierTerminator = specificationWithIgnoredTrailingContents[startIndexOfVersionSpecifier...].firstIndex(where: { $0 == ";" }) ?? specificationWithIgnoredTrailingContents.endIndex // ☝️ // Technically, this is looking for the position of the first ";" only, not the first line terminator. However, because the Swift tools version specification does not contain any line terminator, we can safely search just the first ";". @@ -624,18 +624,21 @@ extension ManifestLoader { let regex = try! RegEx(pattern: #"^Package@swift-(\d+)(?:\.(\d+))?(?:\.(\d+))?.swift$"#) // Collect all version-specific manifests at the given package path. - let versionSpecificManifests = Dictionary(contents.compactMap{ file -> (ToolsVersion, String)? in - let parsedVersion = regex.matchGroups(in: file) - guard parsedVersion.count == 1, parsedVersion[0].count == 3 else { - return nil - } + let versionSpecificManifests = Dictionary( + contents.compactMap { file -> (ToolsVersion, String)? in + let parsedVersion = regex.matchGroups(in: file) + guard parsedVersion.count == 1, parsedVersion[0].count == 3 else { + return nil + } - let major = Int(parsedVersion[0][0])! - let minor = parsedVersion[0][1].isEmpty ? 0 : Int(parsedVersion[0][1])! - let patch = parsedVersion[0][2].isEmpty ? 0 : Int(parsedVersion[0][2])! + let major = Int(parsedVersion[0][0])! + let minor = parsedVersion[0][1].isEmpty ? 0 : Int(parsedVersion[0][1])! + let patch = parsedVersion[0][2].isEmpty ? 0 : Int(parsedVersion[0][2])! - return (ToolsVersion(version: Version(major, minor, patch)), file) - }, uniquingKeysWith: { $1 }) + return (ToolsVersion(version: Version(major, minor, patch)), file) + }, + uniquingKeysWith: { $1 } + ) let regularManifest = packagePath.appending(component: Manifest.filename) @@ -644,9 +647,8 @@ extension ManifestLoader { let regularManifestToolsVersion: ToolsVersion do { regularManifestToolsVersion = try ToolsVersionParser.parse(manifestPath: regularManifest, fileSystem: fileSystem) - } - catch let error as UnsupportedToolsVersion where error.packageToolsVersion == .v3 { - regularManifestToolsVersion = .v3 + } catch let error as UnsupportedToolsVersion where error.packageToolsVersion == .v3 { + regularManifestToolsVersion = .v3 } // Find the newest version-specific manifest that is compatible with the current tools version. @@ -662,8 +664,7 @@ extension ManifestLoader { let versionSpecificManifestToolsVersion: ToolsVersion if versionSpecificCandidate < .v4 { versionSpecificManifestToolsVersion = .v3 - } - else { + } else { versionSpecificManifestToolsVersion = try ToolsVersionParser.parse(manifestPath: versionSpecificManifest, fileSystem: fileSystem) } diff --git a/Sources/PackageMetadata/PackageMetadata.swift b/Sources/PackageMetadata/PackageMetadata.swift index 8622c1181d7..3bb6ba99c43 100644 --- a/Sources/PackageMetadata/PackageMetadata.swift +++ b/Sources/PackageMetadata/PackageMetadata.swift @@ -145,8 +145,6 @@ public struct PackageSearchClient { baseURL.appendingPathComponent("raw").appendingPathComponent(defaultBranch).appendingPathComponent("README.md") } - - private func guessReadMeURL(alternateLocations: [SourceControlURL]?) -> URL? { if let alternateURL = alternateLocations?.first { // FIXME: This is pretty crude, we should let the registry metadata provide the value instead. @@ -240,10 +238,12 @@ public struct PackageSearchClient { to: tempPath, progressHandler: nil ) - guard try self.repositoryProvider.isValidDirectory(tempPath), let repository = try await self.repositoryProvider.open( - repository: repositorySpecifier, - at: tempPath - ) as? GitRepository else { + guard try self.repositoryProvider.isValidDirectory(tempPath), + let repository = try await self.repositoryProvider.open( + repository: repositorySpecifier, + at: tempPath + ) as? GitRepository + else { return [] } @@ -298,30 +298,34 @@ public struct PackageSearchClient { // See if the latest package version has readmeURL set guard let version = versions.first else { let readmeURL: URL? = self.guessReadMeURL(alternateLocations: metadata.alternateLocations) - return [Package( - identity: identity, - versions: versions, - readmeURL: readmeURL, - // this only makes sense in connection with providing versioned metadata - source: .registry(url: metadata.registry.url) - )] + return [ + Package( + identity: identity, + versions: versions, + readmeURL: readmeURL, + // this only makes sense in connection with providing versioned metadata + source: .registry(url: metadata.registry.url) + ) + ] } let versionMetadata = try? await self.getVersionMetadata(package: identity, version: version) - return [Package( - identity: identity, - versions: versions, - licenseURL: versionMetadata?.licenseURL, - readmeURL: versionMetadata?.readmeURL, - repositoryURLs: versionMetadata?.repositoryURLs, - resources: versionMetadata?.resources ?? [], - author: versionMetadata?.author, - description: versionMetadata?.description, - publishedAt: versionMetadata?.publishedAt, - signingEntity: versionMetadata?.signingEntity, - latestVersion: version, - source: .registry(url: metadata.registry.url) - )] + return [ + Package( + identity: identity, + versions: versions, + licenseURL: versionMetadata?.licenseURL, + readmeURL: versionMetadata?.readmeURL, + repositoryURLs: versionMetadata?.repositoryURLs, + resources: versionMetadata?.resources ?? [], + author: versionMetadata?.author, + description: versionMetadata?.description, + publishedAt: versionMetadata?.publishedAt, + signingEntity: versionMetadata?.signingEntity, + latestVersion: version, + source: .registry(url: metadata.registry.url) + ) + ] } public func lookupIdentities( diff --git a/Sources/PackageModel/BuildConfiguration.swift b/Sources/PackageModel/BuildConfiguration.swift index f11a6341604..1f60cf8db7a 100644 --- a/Sources/PackageModel/BuildConfiguration.swift +++ b/Sources/PackageModel/BuildConfiguration.swift @@ -17,8 +17,8 @@ public enum BuildConfiguration: String, CaseIterable, Encodable, Sendable { public var dirname: String { switch self { - case .debug: return "debug" - case .release: return "release" + case .debug: return "debug" + case .release: return "release" } } } diff --git a/Sources/PackageModel/BuildSettings.swift b/Sources/PackageModel/BuildSettings.swift index 3320bdf6307..d9aa0dd462c 100644 --- a/Sources/PackageModel/BuildSettings.swift +++ b/Sources/PackageModel/BuildSettings.swift @@ -58,7 +58,7 @@ public enum BuildSettings { public init(values: [String] = [], conditions: [PackageCondition] = []) { self.values = values - self.default = false // TODO(franz): Check again + self.default = false // TODO(franz): Check again self.conditions = conditions } } diff --git a/Sources/PackageModel/DependencyMapper.swift b/Sources/PackageModel/DependencyMapper.swift index 2d0245e12df..c563844ecc2 100644 --- a/Sources/PackageModel/DependencyMapper.swift +++ b/Sources/PackageModel/DependencyMapper.swift @@ -31,11 +31,12 @@ public struct DefaultDependencyMapper: DependencyMapper { public func mappedDependency(_ dependency: MappablePackageDependency, fileSystem: FileSystem) throws -> PackageDependency { // clean up variants of path based dependencies - let dependencyLocationString = try self.normalizeDependencyLocation( - dependency: dependency, - parentPackagePath: dependency.parentPackagePath, - fileSystem: fileSystem - ) ?? dependency.locationString + let dependencyLocationString = + try self.normalizeDependencyLocation( + dependency: dependency, + parentPackagePath: dependency.parentPackagePath, + fileSystem: fileSystem + ) ?? dependency.locationString // location mapping (aka mirrors) if any let mappedLocationString = self.identityResolver.mappedLocation(for: dependencyLocationString) @@ -114,10 +115,10 @@ public struct DefaultDependencyMapper: DependencyMapper { let location = String(dependencyLocation.dropFirst(Self.filePrefix.count)) let hostnameComponent = location.prefix(while: { $0 != "/" }) guard hostnameComponent.isEmpty else { - if hostnameComponent == ".." { - throw DependencyMappingError.invalidFileURL("file:// URLs cannot be relative, did you mean to use '.package(path:)'?") - } - throw DependencyMappingError.invalidFileURL("file:// URLs with hostnames are not supported, are you missing a '/'?") + if hostnameComponent == ".." { + throw DependencyMappingError.invalidFileURL("file:// URLs cannot be relative, did you mean to use '.package(path:)'?") + } + throw DependencyMappingError.invalidFileURL("file:// URLs with hostnames are not supported, are you missing a '/'?") } return try AbsolutePath(validating: location).pathString // if the location has a scheme, assume a URL and nothing to normalize diff --git a/Sources/PackageModel/EnabledTrait.swift b/Sources/PackageModel/EnabledTrait.swift index f5692528f98..aa3d6ee2f02 100644 --- a/Sources/PackageModel/EnabledTrait.swift +++ b/Sources/PackageModel/EnabledTrait.swift @@ -86,7 +86,7 @@ public struct EnabledTraitsMap { /// or when the `default` trait is explicitly requested. var _defaultSetters: [PackageIdentity: Set] = [:] - init() { } + init() {} init(_ traits: [PackageIdentity: EnabledTraits]) { self.traits = traits @@ -95,7 +95,7 @@ public struct EnabledTraitsMap { private var storage = ThreadSafeBox(Storage()) - public init() { } + public init() {} public subscript(key: String) -> EnabledTraits { get { self[PackageIdentity(key)] } @@ -351,15 +351,15 @@ extension EnabledTrait: Equatable { // When comparing two `EnabledTraits`, if the names are the same then // we know that these two objects are referring to the same trait of a package. // In this case, the two objects should be combined into one. - public static func ==(lhs: EnabledTrait, rhs: EnabledTrait) -> Bool { + public static func == (lhs: EnabledTrait, rhs: EnabledTrait) -> Bool { return lhs.name == rhs.name } - public static func ==(lhs: EnabledTrait, rhs: String) -> Bool { + public static func == (lhs: EnabledTrait, rhs: String) -> Bool { return lhs.name == rhs } - public static func ==(lhs: String, rhs: EnabledTrait) -> Bool { + public static func == (lhs: String, rhs: EnabledTrait) -> Bool { return lhs == rhs.name } } @@ -367,7 +367,7 @@ extension EnabledTrait: Equatable { // MARK: EnabledTrait + Comparable extension EnabledTrait: Comparable { - public static func <(lhs: EnabledTrait, rhs: EnabledTrait) -> Bool { + public static func < (lhs: EnabledTrait, rhs: EnabledTrait) -> Bool { return lhs.name < rhs.name } } @@ -458,7 +458,7 @@ public struct EnabledTraits: Hashable { self._traits = IdentifiableSet(traits) } - public static func ==(_ lhs: EnabledTraits, _ rhs: EnabledTraits) -> Bool { + public static func == (_ lhs: EnabledTraits, _ rhs: EnabledTraits) -> Bool { lhs._traits.names == rhs._traits.names } } @@ -537,11 +537,11 @@ extension EnabledTraits: Collection { return EnabledTraits(transformedTraits) } - public static func ==(_ lhs: EnabledTraits, _ rhs: C) -> Bool where C.Element == Element { + public static func == (_ lhs: EnabledTraits, _ rhs: C) -> Bool where C.Element == Element { lhs._traits.names == rhs.names } - public static func ==(_ lhs: C, _ rhs: EnabledTraits) -> Bool where C.Element == Element { + public static func == (_ lhs: C, _ rhs: EnabledTraits) -> Bool where C.Element == Element { lhs.names == rhs._traits.names } } @@ -583,7 +583,6 @@ extension Collection where Element == EnabledTrait { } } - // MARK: - IdentifiableSet + EnabledTrait extension IdentifiableSet where Element == EnabledTrait { @@ -603,4 +602,3 @@ extension IdentifiableSet where Element == EnabledTrait { return updatedContents } } - diff --git a/Sources/PackageModel/InstalledSwiftPMConfiguration.swift b/Sources/PackageModel/InstalledSwiftPMConfiguration.swift index a35063a1be7..ad815060ebd 100644 --- a/Sources/PackageModel/InstalledSwiftPMConfiguration.swift +++ b/Sources/PackageModel/InstalledSwiftPMConfiguration.swift @@ -74,10 +74,11 @@ extension InstalledSwiftPMConfiguration: Codable { Version.self, forKey: CodingKeys.swiftSyntaxVersionForMacroTemplate ) - self.swiftTestingVersionForTestTemplate = try container.decodeIfPresent( - Version.self, - forKey: CodingKeys.swiftTestingVersionForTestTemplate - ) ?? InstalledSwiftPMConfiguration.defaultSwiftTestingVersionForTestTemplate + self.swiftTestingVersionForTestTemplate = + try container.decodeIfPresent( + Version.self, + forKey: CodingKeys.swiftTestingVersionForTestTemplate + ) ?? InstalledSwiftPMConfiguration.defaultSwiftTestingVersionForTestTemplate } public func encode(to encoder: any Encoder) throws { @@ -92,5 +93,5 @@ extension InstalledSwiftPMConfiguration: Codable { self.swiftTestingVersionForTestTemplate, forKey: CodingKeys.swiftTestingVersionForTestTemplate ) - } + } } diff --git a/Sources/PackageModel/Manifest/Manifest+Traits.swift b/Sources/PackageModel/Manifest/Manifest+Traits.swift index 061d89a3477..407e4267692 100644 --- a/Sources/PackageModel/Manifest/Manifest+Traits.swift +++ b/Sources/PackageModel/Manifest/Manifest+Traits.swift @@ -118,7 +118,7 @@ extension Manifest { // Validate each trait to assure it's defined in the current package. for trait in enabledTraits { - try validateTrait(trait) + try validateTrait(trait) } let areDefaultsEnabled = enabledTraits.contains("default") @@ -161,7 +161,6 @@ extension Manifest { } } - // MARK: - Traits /// Helper methods to calculate states of the manifest and its dependencies when given a set of enabled traits. @@ -307,7 +306,6 @@ extension Manifest { ) } - let appendedList = enabledTraits.union(transitivelyEnabledTraits) if appendedList.count == enabledTraits.count { break @@ -343,9 +341,9 @@ extension Manifest { /// Computes the set of package dependencies that are used by targets of this manifest. public func usedDependencies(withTraits enabledTraits: EnabledTraits) throws -> (knownPackage: Set, unknownPackage: Set) { let deps = try self.usedTargetDependencies(withTraits: enabledTraits) - .values - .flatMap { $0 } - .compactMap(\.package) + .values + .flatMap { $0 } + .compactMap(\.package) var known: Set = [] var unknown: Set = [] @@ -420,10 +418,12 @@ extension Manifest { // Check if any of the traits guarding this dependency is enabled; // if so, the condition is met and the target dependency is considered // to be in an enabled state. - let isEnabled = try traitsToEnable.contains(where: { try self.isTraitEnabled( - .init(stringLiteral: $0), - enabledTraits, - ) }) + let isEnabled = try traitsToEnable.contains(where: { + try self.isTraitEnabled( + .init(stringLiteral: $0), + enabledTraits, + ) + }) return traitsToEnable.isEmpty || isEnabled } @@ -451,13 +451,17 @@ extension Manifest { let targetDependenciesForPackageDependency = self.targets.flatMap({ $0.dependencies }) .filter({ - $0.package?.caseInsensitiveCompare(dependency.identity.description) == .orderedSame - }) + $0.package?.caseInsensitiveCompare(dependency.identity.description) == .orderedSame + }) // Determine whether the current set of enabled traits still gate the package dependency // across targets. - let isTraitGuarded = targetDependenciesForPackageDependency.isEmpty ? false : targetDependenciesForPackageDependency.filter({ $0.condition?.traits != nil }).allSatisfy({ self.isTargetDependencyTraitGuarded($0, enabledTraits: enabledTraits) - }) + let isTraitGuarded = + targetDependenciesForPackageDependency.isEmpty + ? false + : targetDependenciesForPackageDependency.filter({ $0.condition?.traits != nil }).allSatisfy({ + self.isTargetDependencyTraitGuarded($0, enabledTraits: enabledTraits) + }) // Since we only omit a package dependency that is only guarded by traits, determine // whether this dependency is used elsewhere without traits. @@ -548,22 +552,22 @@ extension TraitError: CustomStringConvertible { if explicitlyEnabledTraits.isEmpty { if let parent = explicitlyEnabledTraits.disabledBy { return """ - Disabled default traits by \(parent.description) on package \(package) that declares no traits. This is prohibited to allow packages to adopt traits initially without causing an API break. - """ + Disabled default traits by \(parent.description) on package \(package) that declares no traits. This is prohibited to allow packages to adopt traits initially without causing an API break. + """ } else { return """ - Disabled default traits on package \(package) that declares no traits. This is prohibited to allow packages to adopt traits initially without causing an API break. - """ + Disabled default traits on package \(package) that declares no traits. This is prohibited to allow packages to adopt traits initially without causing an API break. + """ } } else { if let parent { return """ - Package \(parent) enables traits [\(explicitlyEnabledTraits.joined(separator: ", "))] on package \(package) that declares no traits. - """ + Package \(parent) enables traits [\(explicitlyEnabledTraits.joined(separator: ", "))] on package \(package) that declares no traits. + """ } else { return """ - Traits [\(explicitlyEnabledTraits.joined(separator: ", "))] have been enabled on package \(package) that declares no traits. - """ + Traits [\(explicitlyEnabledTraits.joined(separator: ", "))] have been enabled on package \(package) that declares no traits. + """ } } } diff --git a/Sources/PackageModel/Manifest/Manifest.swift b/Sources/PackageModel/Manifest/Manifest.swift index 5d4220e314f..f2269a77818 100644 --- a/Sources/PackageModel/Manifest/Manifest.swift +++ b/Sources/PackageModel/Manifest/Manifest.swift @@ -157,32 +157,32 @@ public final class Manifest: Sendable { /// Returns the targets required for a particular product filter. public func targetsRequired(for productFilter: ProductFilter) -> [TargetDescription] { #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - // If we have already calculated it, returned the cached value. - if let targets = _requiredTargets[productFilter] { - return targets - } else { - let targets: [TargetDescription] - switch productFilter { - case .everything: - return self.targets - case .specific(let productFilter): - let products = self.products.filter { productFilter.contains($0.name) } - targets = self.targetsRequired(for: products) - } + // If we have already calculated it, returned the cached value. + if let targets = _requiredTargets[productFilter] { + return targets + } else { + let targets: [TargetDescription] + switch productFilter { + case .everything: + return self.targets + case .specific(let productFilter): + let products = self.products.filter { productFilter.contains($0.name) } + targets = self.targetsRequired(for: products) + } - self._requiredTargets[productFilter] = targets - return targets - } + self._requiredTargets[productFilter] = targets + return targets + } #else - // using .nothing as cache key while ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION is false - if let targets = self._requiredTargets[.nothing] { - return targets - } else { - let targets = self.packageKind.isRoot ? self.targets : self.targetsRequired(for: self.products) // using .nothing as cache key while ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION is false - self._requiredTargets[.nothing] = targets - return targets - } + if let targets = self._requiredTargets[.nothing] { + return targets + } else { + let targets = self.packageKind.isRoot ? self.targets : self.targetsRequired(for: self.products) + // using .nothing as cache key while ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION is false + self._requiredTargets[.nothing] = targets + return targets + } #endif } @@ -212,7 +212,7 @@ public final class Manifest: Sendable { var result = false for guardedTargetDeps in traitGuardedDeps[$0.identity.description] ?? [] { if let guardTraits = guardedTargetDeps.condition?.traits, !guardTraits.isEmpty, - let explicitlyEnabledTraits + let explicitlyEnabledTraits { result = result || !guardTraits.allSatisfy { explicitlyEnabledTraits.contains($0) } } @@ -228,7 +228,7 @@ public final class Manifest: Sendable { var result = false for guardedTargetDeps in traitGuardedDeps[$0.identity.description] ?? [] { if let guardTraits = guardedTargetDeps.condition?.traits, !guardTraits.isEmpty, - let explicitlyEnabledTraits + let explicitlyEnabledTraits { result = result || !guardTraits.allSatisfy { explicitlyEnabledTraits.contains($0) } } @@ -244,13 +244,12 @@ public final class Manifest: Sendable { for targetDependency in target.dependencies { guard let dependency = self.packageDependency(referencedBy: targetDependency), - let guardingTraits = traitGuardedTargetDeps[targetDependency] + let guardingTraits = traitGuardedTargetDeps[targetDependency] else { continue } - if guardingTraits.intersection(enabledTraits.names) != guardingTraits - { + if guardingTraits.intersection(enabledTraits.names) != guardingTraits { guardedDependencies.insert(dependency.identity) } } @@ -269,62 +268,64 @@ public final class Manifest: Sendable { _ enabledTraits: EnabledTraits = ["default"] ) throws -> [PackageDependency] { #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - // If we have already calculated it, returned the cached value. - if let dependencies = self._requiredDependencies[productFilter] { - return dependencies - } else { - let targets = self.targetsRequired(for: productFilter) - let dependencies = self.dependenciesRequired( - for: targets, - keepUnused: productFilter == .everything, - traitConfiguration - ) - self._requiredDependencies[productFilter] = dependencies - return dependencies - } + // If we have already calculated it, returned the cached value. + if let dependencies = self._requiredDependencies[productFilter] { + return dependencies + } else { + let targets = self.targetsRequired(for: productFilter) + let dependencies = self.dependenciesRequired( + for: targets, + keepUnused: productFilter == .everything, + traitConfiguration + ) + self._requiredDependencies[productFilter] = dependencies + return dependencies + } #else - guard self.toolsVersion >= .v5_2 && !self.packageKind.isRoot else { - var dependencies = self.dependencies + guard self.toolsVersion >= .v5_2 && !self.packageKind.isRoot else { + var dependencies = self.dependencies dependencies = try dependencies.filter({ let isUsed = try self.isPackageDependencyUsed($0, enabledTraits: enabledTraits) return isUsed }) - return dependencies - } + return dependencies + } - // using .nothing as cache key while ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION is false - if var dependencies = self._requiredDependencies[.nothing] { + // using .nothing as cache key while ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION is false + if var dependencies = self._requiredDependencies[.nothing] { dependencies = try dependencies.filter({ return try self.isPackageDependencyUsed($0, enabledTraits: enabledTraits) }) - return dependencies - } else { - var requiredDependencies: Set = [] - for target in self.targetsRequired(for: self.products) { - for targetDependency in target.dependencies { - guard try self.isTargetDependencyEnabled( - target: target.name, - targetDependency, - enabledTraits: enabledTraits - ) else { continue } - if let dependency = self.packageDependency(referencedBy: targetDependency) { - requiredDependencies.insert(dependency.identity) + return dependencies + } else { + var requiredDependencies: Set = [] + for target in self.targetsRequired(for: self.products) { + for targetDependency in target.dependencies { + guard + try self.isTargetDependencyEnabled( + target: target.name, + targetDependency, + enabledTraits: enabledTraits + ) + else { continue } + if let dependency = self.packageDependency(referencedBy: targetDependency) { + requiredDependencies.insert(dependency.identity) + } } - } - target.pluginUsages?.forEach { - if let dependency = self.packageDependency(referencedBy: $0) { - requiredDependencies.insert(dependency.identity) + target.pluginUsages?.forEach { + if let dependency = self.packageDependency(referencedBy: $0) { + requiredDependencies.insert(dependency.identity) + } } } - } - let dependencies = self.dependencies.filter { requiredDependencies.contains($0.identity) } - // using .nothing as cache key while ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION is false - self._requiredDependencies[.nothing] = dependencies - return dependencies - } + let dependencies = self.dependencies.filter { requiredDependencies.contains($0.identity) } + // using .nothing as cache key while ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION is false + self._requiredDependencies[.nothing] = dependencies + return dependencies + } #endif } @@ -334,40 +335,44 @@ public final class Manifest: Sendable { let targetsByName = Dictionary(targets.map { ($0.name, $0) }, uniquingKeysWith: { $1 }) let productTargetNames = products.flatMap(\.targets) - let dependentTargetNames = transitiveClosure(productTargetNames, successors: { targetName in - - if let target = targetsByName[targetName] { - let dependencies: [String] = target.dependencies.compactMap { dependency in - switch dependency { - case .target(let name, _), - .byName(let name, _): - targetsByName.keys.contains(name) ? name : nil - default: - nil - } - } - - let plugins: [String] = target.pluginUsages?.compactMap { pluginUsage in - switch pluginUsage { - case .plugin(name: let name, package: nil): - if targetsByName.keys.contains(name) { - name - } else if let targetName = productsByName[name]?.targets.first { - targetName - } else { + let dependentTargetNames = transitiveClosure( + productTargetNames, + successors: { targetName in + + if let target = targetsByName[targetName] { + let dependencies: [String] = target.dependencies.compactMap { dependency in + switch dependency { + case .target(let name, _), + .byName(let name, _): + targetsByName.keys.contains(name) ? name : nil + default: nil } - default: - nil } - } ?? [] - return dependencies + plugins - } + let plugins: [String] = + target.pluginUsages?.compactMap { pluginUsage in + switch pluginUsage { + case .plugin(name: let name, package: nil): + if targetsByName.keys.contains(name) { + name + } else if let targetName = productsByName[name]?.targets.first { + targetName + } else { + nil + } + default: + nil + } + } ?? [] + + return dependencies + plugins + } - return [] + return [] - }) + } + ) let requiredTargetNames = Set(productTargetNames).union(dependentTargetNames) let requiredTargets = requiredTargetNames.compactMap { targetsByName[$0] } @@ -431,7 +436,7 @@ public final class Manifest: Sendable { switch targetDependency { case .product(_, package: let name?, _, _), - .byName(name: let name, _): + .byName(name: let name, _): packageName = name default: return nil @@ -488,7 +493,7 @@ public final class Manifest: Sendable { case .target: break case .product(let product, let package, _, _): - if let package { // ≥ 5.2 + if let package { // ≥ 5.2 if !self.register( product: product, inPackage: self.packageIdentity(referencedBy: package), @@ -499,7 +504,7 @@ public final class Manifest: Sendable { // Treating it as unknown gracefully allows resolution to continue for now. registry.unknown.insert(product) } - } else { // < 5.2 + } else { // < 5.2 registry.unknown.insert(product) } case .byName(let product, _): @@ -511,7 +516,7 @@ public final class Manifest: Sendable { } else { registry.unknown.insert(product) } - } else { // ≥ 5.2 + } else { // ≥ 5.2 // If a by‐name entry is a product, it must be in a package of the same name. if !self.register( product: product, @@ -631,9 +636,9 @@ extension Manifest: CustomStringConvertible { extension Manifest: Encodable { private enum CodingKeys: CodingKey { case name, path, url, version, targetMap, toolsVersion, - pkgConfig, providers, cLanguageStandard, cxxLanguageStandard, swiftLanguageVersions, - dependencies, products, targets, traits, platforms, packageKind, revision, - defaultLocalization + pkgConfig, providers, cLanguageStandard, cxxLanguageStandard, swiftLanguageVersions, + dependencies, products, targets, traits, platforms, packageKind, revision, + defaultLocalization } /// Coding user info key for dump-package command. diff --git a/Sources/PackageModel/Manifest/PackageConditionDescription.swift b/Sources/PackageModel/Manifest/PackageConditionDescription.swift index b8257bc5650..ffc3043bf72 100644 --- a/Sources/PackageModel/Manifest/PackageConditionDescription.swift +++ b/Sources/PackageModel/Manifest/PackageConditionDescription.swift @@ -107,7 +107,6 @@ public struct ConfigurationCondition: Hashable, Sendable { } } - /// A configuration condition implies that an assignment is valid on /// a particular build configuration. public struct TraitCondition: Hashable, Sendable { @@ -121,4 +120,3 @@ public struct TraitCondition: Hashable, Sendable { return true } } - diff --git a/Sources/PackageModel/Manifest/PackageDependencyDescription.swift b/Sources/PackageModel/Manifest/PackageDependencyDescription.swift index d979d90e79b..39e856b7afe 100644 --- a/Sources/PackageModel/Manifest/PackageDependencyDescription.swift +++ b/Sources/PackageModel/Manifest/PackageDependencyDescription.swift @@ -96,7 +96,7 @@ public enum PackageDependency: Equatable, Hashable, Sendable { case fileSystem(FileSystem) case sourceControl(SourceControl) case registry(Registry) - + public struct FileSystem: Equatable, Hashable, Encodable, Sendable { public let identity: PackageIdentity public let nameForTargetDependencyResolutionOnly: String? @@ -301,7 +301,7 @@ public enum PackageDependency: Equatable, Hashable, Sendable { traits: traits ) } - + public static func remoteSourceControl( identity: PackageIdentity, nameForTargetDependencyResolutionOnly: String?, @@ -406,11 +406,11 @@ public enum PackageDependency: Equatable, Hashable, Sendable { extension Range { public static func upToNextMajor(from version: Version) -> Range where Bound == Version { - return version ..< Version(version.major + 1, 0, 0) + return version.. Range where Bound == Version { - return version ..< Version(version.major, version.minor + 1, 0) + return version.." - ) } - if pkgConfig != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pkgConfig", - value: pkgConfig ?? "" - ) } - if providers != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "providers", - value: String(describing: providers!) - ) } - if pluginCapability != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pluginCapability", - value: String(describing: pluginCapability!) - ) } - if checksum != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "checksum", - value: checksum ?? "" - ) } + if url != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "url", + value: url ?? "" + ) + } + if pkgConfig != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pkgConfig", + value: pkgConfig ?? "" + ) + } + if providers != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "providers", + value: String(describing: providers!) + ) + } + if pluginCapability != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pluginCapability", + value: String(describing: pluginCapability!) + ) + } + if checksum != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "checksum", + value: checksum ?? "" + ) + } case .system: - if !dependencies.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "dependencies", - value: String(describing: dependencies) - ) } - if !exclude.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "exclude", - value: String(describing: exclude) - ) } - if sources != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "sources", - value: String(describing: sources!) - ) } - if !resources.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "resources", - value: String(describing: resources) - ) } - if publicHeadersPath != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "publicHeadersPath", - value: publicHeadersPath ?? "" - ) } - if pluginCapability != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pluginCapability", - value: String(describing: pluginCapability!) - ) } - if !settings.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "settings", - value: String(describing: settings) - ) } - if checksum != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "checksum", - value: checksum ?? "" - ) } - if pluginUsages != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pluginUsages", - value: String(describing: pluginUsages!) - ) } + if !dependencies.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "dependencies", + value: String(describing: dependencies) + ) + } + if !exclude.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "exclude", + value: String(describing: exclude) + ) + } + if sources != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "sources", + value: String(describing: sources!) + ) + } + if !resources.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "resources", + value: String(describing: resources) + ) + } + if publicHeadersPath != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "publicHeadersPath", + value: publicHeadersPath ?? "" + ) + } + if pluginCapability != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pluginCapability", + value: String(describing: pluginCapability!) + ) + } + if !settings.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "settings", + value: String(describing: settings) + ) + } + if checksum != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "checksum", + value: checksum ?? "" + ) + } + if pluginUsages != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pluginUsages", + value: String(describing: pluginUsages!) + ) + } case .binary: if path == nil && url == nil { throw Error.binaryTargetRequiresEitherPathOrURL(targetName: name) } - if !dependencies.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "dependencies", - value: String(describing: dependencies) - ) } - if !exclude.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "exclude", - value: String(describing: exclude) - ) } - if sources != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "sources", - value: String(describing: sources!) - ) } - if !resources.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "resources", - value: String(describing: resources) - ) } - if publicHeadersPath != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "publicHeadersPath", - value: publicHeadersPath ?? "" - ) } - if pkgConfig != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pkgConfig", - value: pkgConfig ?? "" - ) } - if providers != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "providers", - value: String(describing: providers!) - ) } - if pluginCapability != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pluginCapability", - value: String(describing: pluginCapability!) - ) } - if !settings.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "settings", - value: String(describing: settings) - ) } - if pluginUsages != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pluginUsages", - value: String(describing: pluginUsages!) - ) } + if !dependencies.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "dependencies", + value: String(describing: dependencies) + ) + } + if !exclude.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "exclude", + value: String(describing: exclude) + ) + } + if sources != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "sources", + value: String(describing: sources!) + ) + } + if !resources.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "resources", + value: String(describing: resources) + ) + } + if publicHeadersPath != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "publicHeadersPath", + value: publicHeadersPath ?? "" + ) + } + if pkgConfig != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pkgConfig", + value: pkgConfig ?? "" + ) + } + if providers != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "providers", + value: String(describing: providers!) + ) + } + if pluginCapability != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pluginCapability", + value: String(describing: pluginCapability!) + ) + } + if !settings.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "settings", + value: String(describing: settings) + ) + } + if pluginUsages != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pluginUsages", + value: String(describing: pluginUsages!) + ) + } case .plugin: if pluginCapability == nil { throw Error.pluginTargetRequiresPluginCapability(targetName: name) } - if url != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "url", - value: url ?? "" - ) } - if !resources.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "resources", - value: String(describing: resources) - ) } - if publicHeadersPath != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "publicHeadersPath", - value: publicHeadersPath ?? "" - ) } - if pkgConfig != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pkgConfig", - value: pkgConfig ?? "" - ) } - if providers != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "providers", - value: String(describing: providers!) - ) } - if !settings.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "settings", - value: String(describing: settings) - ) } - if pluginUsages != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pluginUsages", - value: String(describing: pluginUsages!) - ) } + if url != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "url", + value: url ?? "" + ) + } + if !resources.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "resources", + value: String(describing: resources) + ) + } + if publicHeadersPath != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "publicHeadersPath", + value: publicHeadersPath ?? "" + ) + } + if pkgConfig != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pkgConfig", + value: pkgConfig ?? "" + ) + } + if providers != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "providers", + value: String(describing: providers!) + ) + } + if !settings.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "settings", + value: String(describing: settings) + ) + } + if pluginUsages != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pluginUsages", + value: String(describing: pluginUsages!) + ) + } case .macro: - if url != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "url", - value: url ?? "" - ) } - if !resources.isEmpty { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "resources", - value: String(describing: resources) - ) } - if publicHeadersPath != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "publicHeadersPath", - value: publicHeadersPath ?? "" - ) } - if pkgConfig != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pkgConfig", - value: pkgConfig ?? "" - ) } - if providers != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "providers", - value: String(describing: providers!) - ) } - if pluginCapability != nil { throw Error.disallowedPropertyInTarget( - targetName: name, - targetType: targetType, - propertyName: "pluginCapability", - value: String(describing: pluginCapability!) - ) } + if url != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "url", + value: url ?? "" + ) + } + if !resources.isEmpty { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "resources", + value: String(describing: resources) + ) + } + if publicHeadersPath != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "publicHeadersPath", + value: publicHeadersPath ?? "" + ) + } + if pkgConfig != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pkgConfig", + value: pkgConfig ?? "" + ) + } + if providers != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "providers", + value: String(describing: providers!) + ) + } + if pluginCapability != nil { + throw Error.disallowedPropertyInTarget( + targetName: name, + targetType: targetType, + propertyName: "pluginCapability", + value: String(describing: pluginCapability!) + ) + } } self.name = name @@ -600,9 +674,7 @@ private enum Error: LocalizedError, Equatable { case .pluginTargetRequiresPluginCapability(let targetName): "plugin target '\(targetName)' must define a plugin capability" case .disallowedPropertyInTarget(let targetName, let targetType, let propertyName, let value): - "target '\(targetName)' is assigned a property '\(propertyName)' which is not accepted " + - "for the \(targetType) target type. The current property value has " + - "the following representation: \(value)." + "target '\(targetName)' is assigned a property '\(propertyName)' which is not accepted " + "for the \(targetType) target type. The current property value has " + "the following representation: \(value)." } } } diff --git a/Sources/PackageModel/ManifestSourceGeneration.swift b/Sources/PackageModel/ManifestSourceGeneration.swift index 9c9a19a3a2d..f85b9b4b48a 100644 --- a/Sources/PackageModel/ManifestSourceGeneration.swift +++ b/Sources/PackageModel/ManifestSourceGeneration.swift @@ -19,16 +19,16 @@ import Foundation /// mechanical editing of package manifests. Rather, it is intended for such /// tasks as manifest creation as part of package instantiation, etc. extension Manifest { - + /// Generates and returns a string containing the contents of the manifest /// in canonical declarative form. - /// + /// /// - Parameters: /// - packageDirectory: Directory of the manifest's package (for purposes of making strings relative). /// - toolsVersionHeaderComment: Optional string to add to the `swift-tools-version` header (it will be ignored). /// - additionalImportModuleNames: Names of any modules to import besides PackageDescription (would commonly contain custom product type definitions). /// - customProductTypeSourceGenerator: Closure that will be called once for each custom product type in the manifest; it should return a SourceCodeFragment for the product type. - /// + /// /// Returns: a string containing the full source code for the manifest. public func generateManifestFileContents( packageDirectory: AbsolutePath, @@ -38,15 +38,16 @@ extension Manifest { overridingToolsVersion: ToolsVersion? = nil ) rethrows -> String { let toolsVersion = overridingToolsVersion ?? self.toolsVersion - + // Generate the source code fragment for the top level of the package // expression. let packageExprFragment = try SourceCodeFragment( from: self, packageDirectory: packageDirectory, customProductTypeSourceGenerator: customProductTypeSourceGenerator, - toolsVersion: toolsVersion) - + toolsVersion: toolsVersion + ) + // Generate the source code from the module names and code fragment. // We only write out the major and minor (not patch) versions of the // tools version, since the patch version doesn't change semantics. @@ -64,7 +65,6 @@ extension Manifest { /// Constructs and returns a SourceCodeFragment that represents the instantiation of a custom product type with the specified identifier and having the given serialized parameters (the contents of whom are a private matter between the serialized form in PackageDescription and the client). The generated source code should, if evaluated as a part of a package manifest, result in the same serialized parameters. public typealias ManifestCustomProductTypeSourceGenerator = (ProductDescription) throws -> SourceCodeFragment? - /// Convenience initializers for package manifest structures. fileprivate extension SourceCodeFragment { @@ -76,29 +76,29 @@ fileprivate extension SourceCodeFragment { toolsVersion: ToolsVersion ) rethrows { var params: [SourceCodeFragment] = [] - + params.append(SourceCodeFragment(key: "name", string: manifest.displayName)) - + if let defaultLoc = manifest.defaultLocalization { params.append(SourceCodeFragment(key: "defaultLocalization", string: defaultLoc)) } - + if !manifest.platforms.isEmpty { - let nodes = manifest.platforms.map{ SourceCodeFragment(from: $0) } + let nodes = manifest.platforms.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "platforms", subnodes: nodes)) } - + if let pkgConfig = manifest.pkgConfig { params.append(SourceCodeFragment(key: "pkgConfig", string: pkgConfig)) } - + if let systemPackageProviders = manifest.providers, !systemPackageProviders.isEmpty { - let nodes = systemPackageProviders.map{ SourceCodeFragment(from: $0) } + let nodes = systemPackageProviders.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "providers", subnodes: nodes)) } if !manifest.products.isEmpty { - let nodes = try manifest.products.map{ try SourceCodeFragment(from: $0, customProductTypeSourceGenerator: customProductTypeSourceGenerator, toolsVersion: toolsVersion) } + let nodes = try manifest.products.map { try SourceCodeFragment(from: $0, customProductTypeSourceGenerator: customProductTypeSourceGenerator, toolsVersion: toolsVersion) } params.append(SourceCodeFragment(key: "products", subnodes: nodes)) } @@ -108,17 +108,17 @@ fileprivate extension SourceCodeFragment { } if !manifest.dependencies.isEmpty { - let nodes = manifest.dependencies.map{ SourceCodeFragment(from: $0, pathAnchor: packageDirectory) } + let nodes = manifest.dependencies.map { SourceCodeFragment(from: $0, pathAnchor: packageDirectory) } params.append(SourceCodeFragment(key: "dependencies", subnodes: nodes)) } if !manifest.targets.isEmpty { - let nodes = manifest.targets.map{ SourceCodeFragment(from: $0) } + let nodes = manifest.targets.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "targets", subnodes: nodes)) } - + if let swiftLanguageVersions = manifest.swiftLanguageVersions { - let nodes = swiftLanguageVersions.map{ SourceCodeFragment(from: $0) } + let nodes = swiftLanguageVersions.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "swiftLanguageVersions", subnodes: nodes, multiline: false)) } @@ -136,7 +136,7 @@ fileprivate extension SourceCodeFragment { self.init("Package", delimiters: .parentheses, subnodes: params) } - + /// Instantiates a SourceCodeFragment to represent a single platform. init(from platform: PlatformDescription) { // NOTE: This could be cleaned up to use the nicer version accessors. @@ -156,10 +156,10 @@ fileprivate extension SourceCodeFragment { case "driverkit": self.init(enum: "driverKit", string: platform.version) default: - self.init(enum: "custom", subnodes: [ .init(string: platform.platformName), .init(key: "versionString", string: platform.version) ]) + self.init(enum: "custom", subnodes: [.init(string: platform.platformName), .init(key: "versionString", string: platform.version)]) } } - + /// Instantiates a SourceCodeFragment to represent a single package dependency. init(from dependency: PackageDependency, pathAnchor: AbsolutePath) { var params: [SourceCodeFragment] = [] @@ -201,8 +201,7 @@ fileprivate extension SourceCodeFragment { if let traits = dependency.traits { // If only `.defaults` is specified, do not output `traits:` . // This is because `traits:` is not available in toolchains earlier than 6.1. - let isDefault = traits.count == 1 && - traits.allSatisfy(\.isDefaultsCase) + let isDefault = traits.count == 1 && traits.allSatisfy(\.isDefaultsCase) if !isDefault { let traits = traits.sorted { a, b in @@ -236,10 +235,13 @@ fileprivate extension SourceCodeFragment { subnode: SourceCodeFragment(from: condition) ) - self.init(enum: "trait", subnodes: [ - SourceCodeFragment(key: "name", string: trait.name), - conditionNode - ]) + self.init( + enum: "trait", + subnodes: [ + SourceCodeFragment(key: "name", string: trait.name), + conditionNode, + ] + ) } init(from condition: PackageDependency.Trait.Condition) { @@ -309,8 +311,7 @@ fileprivate extension SourceCodeFragment { } } self.init(enum: "iOSApplication", subnodes: params, multiline: true) - } - else { + } else { self.init(enum: "executable", subnodes: params, multiline: true) } case .snippet: @@ -365,14 +366,14 @@ fileprivate extension SourceCodeFragment { var params: [SourceCodeFragment] = [] params.append(SourceCodeFragment(key: "name", string: target.name)) - + if let pluginCapability = target.pluginCapability { let node = SourceCodeFragment(from: pluginCapability) params.append(SourceCodeFragment(key: "capability", subnode: node)) } if !target.dependencies.isEmpty { - let nodes = target.dependencies.map{ SourceCodeFragment(from: $0) } + let nodes = target.dependencies.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "dependencies", subnodes: nodes)) } @@ -393,7 +394,7 @@ fileprivate extension SourceCodeFragment { } if !target.resources.isEmpty { - let nodes = target.resources.map{ SourceCodeFragment(from: $0) } + let nodes = target.resources.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "resources", subnodes: nodes)) } @@ -404,40 +405,40 @@ fileprivate extension SourceCodeFragment { if let pkgConfig = target.pkgConfig { params.append(SourceCodeFragment(key: "pkgConfig", string: pkgConfig)) } - + if let systemPackageProviders = target.providers, !systemPackageProviders.isEmpty { - let nodes = systemPackageProviders.map{ SourceCodeFragment(from: $0) } + let nodes = systemPackageProviders.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "providers", subnodes: nodes)) } - let cSettings = target.settings.filter{ $0.tool == .c } + let cSettings = target.settings.filter { $0.tool == .c } if !cSettings.isEmpty { - let nodes = cSettings.map{ SourceCodeFragment(from: $0) } + let nodes = cSettings.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "cSettings", subnodes: nodes)) } - let cxxSettings = target.settings.filter{ $0.tool == .cxx } + let cxxSettings = target.settings.filter { $0.tool == .cxx } if !cxxSettings.isEmpty { - let nodes = cxxSettings.map{ SourceCodeFragment(from: $0) } + let nodes = cxxSettings.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "cxxSettings", subnodes: nodes)) } - let swiftSettings = target.settings.filter{ $0.tool == .swift } + let swiftSettings = target.settings.filter { $0.tool == .swift } if !swiftSettings.isEmpty { - let nodes = swiftSettings.map{ SourceCodeFragment(from: $0) } + let nodes = swiftSettings.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "swiftSettings", subnodes: nodes)) } - let linkerSettings = target.settings.filter{ $0.tool == .linker } + let linkerSettings = target.settings.filter { $0.tool == .linker } if !linkerSettings.isEmpty { - let nodes = linkerSettings.map{ SourceCodeFragment(from: $0) } + let nodes = linkerSettings.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "linkerSettings", subnodes: nodes)) } if let checksum = target.checksum { params.append(SourceCodeFragment(key: "checksum", string: checksum)) } - + switch target.type { case .regular: self.init(enum: "target", subnodes: params, multiline: true) @@ -467,7 +468,7 @@ fileprivate extension SourceCodeFragment { params.append(SourceCodeFragment(key: "condition", subnode: SourceCodeFragment(from: condition))) } self.init(enum: "target", subnodes: params) - + case .product(name: let name, package: let packageName, moduleAliases: let aliases, condition: let condition): params.append(SourceCodeFragment(key: "name", string: name)) if let packageName { @@ -481,19 +482,18 @@ fileprivate extension SourceCodeFragment { params.append(SourceCodeFragment(key: "condition", subnode: SourceCodeFragment(from: condition))) } self.init(enum: "product", subnodes: params) - + case .byName(name: let name, condition: let condition): if let condition { params.append(SourceCodeFragment(key: "name", string: name)) params.append(SourceCodeFragment(key: "condition", subnode: SourceCodeFragment(from: condition))) self.init(enum: "byName", subnodes: params) - } - else { + } else { self.init(name.quotedForPackageManifest) } } } - + /// Instantiates a SourceCodeFragment to represent a single package condition. init(from condition: PackageConditionDescription) { var params: [SourceCodeFragment] = [] @@ -529,9 +529,12 @@ fileprivate extension SourceCodeFragment { } if let traits = condition.traits { params.append( - SourceCodeFragment(key: "traits", subnodes: traits.sorted().map { trait in - SourceCodeFragment(string: trait) - }) + SourceCodeFragment( + key: "traits", + subnodes: traits.sorted().map { trait in + SourceCodeFragment(string: trait) + } + ) ) } self.init(enum: "when", subnodes: params) @@ -600,7 +603,7 @@ fileprivate extension SourceCodeFragment { var params: [SourceCodeFragment] = [] params.append(SourceCodeFragment(key: "intent", subnode: .init(from: intent))) if !permissions.isEmpty { - params.append(SourceCodeFragment(key: "permissions", subnodes: permissions.map{ .init(from: $0) })) + params.append(SourceCodeFragment(key: "permissions", subnodes: permissions.map { .init(from: $0) })) } self.init(enum: "command", subnodes: params) } @@ -616,7 +619,7 @@ fileprivate extension SourceCodeFragment { case .custom(let verb, let description): let params = [ SourceCodeFragment(key: "verb", string: verb), - SourceCodeFragment(key: "description", string: description) + SourceCodeFragment(key: "description", string: description), ] self.init(enum: "custom", subnodes: params) } @@ -664,7 +667,7 @@ fileprivate extension SourceCodeFragment { } self.init(enum: setting.kind.name, subnodes: params) case .strictMemorySafety: - self.init(enum: setting.kind.name, subnodes: []) + self.init(enum: setting.kind.name, subnodes: []) case .define(let value): let parts = value.split(separator: "=", maxSplits: 1) assert(parts.count == 1 || parts.count == 2) @@ -756,8 +759,7 @@ fileprivate extension SourceCodeFragment { case let .asset(name): if toolsVersion < .v5_6 { params.append(SourceCodeFragment(key: "iconAssetName", string: "\(name)")) - } - else { + } else { params.append(SourceCodeFragment(key: "appIcon", enum: "asset", string: "\(name)")) } } @@ -769,19 +771,29 @@ fileprivate extension SourceCodeFragment { case let .asset(name): if toolsVersion < .v5_6 { params.append(SourceCodeFragment(key: "accentColorAssetName", string: "\(name)")) - } - else { + } else { params.append(SourceCodeFragment(key: "accentColor", enum: "asset", string: "\(name)")) } } } - params.append(SourceCodeFragment(key: "supportedDeviceFamilies", subnodes: appInfo.supportedDeviceFamilies.map{ - SourceCodeFragment(from: $0) - })) - params.append(SourceCodeFragment(key: "supportedInterfaceOrientations", subnodes: appInfo.supportedInterfaceOrientations.map{ SourceCodeFragment(from: $0) - })) + params.append( + SourceCodeFragment( + key: "supportedDeviceFamilies", + subnodes: appInfo.supportedDeviceFamilies.map { + SourceCodeFragment(from: $0) + } + ) + ) + params.append( + SourceCodeFragment( + key: "supportedInterfaceOrientations", + subnodes: appInfo.supportedInterfaceOrientations.map { + SourceCodeFragment(from: $0) + } + ) + ) if !appInfo.capabilities.isEmpty { - params.append(SourceCodeFragment(key: "capabilities", subnodes: appInfo.capabilities.map{ SourceCodeFragment(from: $0) })) + params.append(SourceCodeFragment(key: "capabilities", subnodes: appInfo.capabilities.map { SourceCodeFragment(from: $0) })) } if let appCategory = appInfo.appCategory { params.append(SourceCodeFragment(subnode: SourceCodeFragment(from: appCategory))) @@ -791,12 +803,12 @@ fileprivate extension SourceCodeFragment { } self.init(enum: "init", subnodes: params, multiline: true) } - + /// Instantiates a SourceCodeFragment from a single ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon. init(from placeholderIcon: ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon) { self.init(key: "icon", enum: placeholderIcon.rawValue) } - + /// Instantiates a SourceCodeFragment from a single ProductSetting.IOSAppInfo.AccentColor.PresetColor. init(from presetColor: ProductSetting.IOSAppInfo.AccentColor.PresetColor) { self.init(enum: presetColor.rawValue) @@ -809,7 +821,7 @@ fileprivate extension SourceCodeFragment { /// Instantiates a SourceCodeFragment from a single ProductSetting.IOSAppInfo.DeviceFamilyCondition. init(from deviceFamilyCondition: ProductSetting.IOSAppInfo.DeviceFamilyCondition) { - let deviceFamilyNodes = deviceFamilyCondition.deviceFamilies.map{ SourceCodeFragment(from: $0) } + let deviceFamilyNodes = deviceFamilyCondition.deviceFamilies.map { SourceCodeFragment(from: $0) } let deviceFamiliesList = SourceCodeFragment(key: "deviceFamilies", subnodes: deviceFamilyNodes, multiline: false) self.init(enum: "when", subnodes: [deviceFamiliesList]) } @@ -818,13 +830,13 @@ fileprivate extension SourceCodeFragment { init(from orientation: ProductSetting.IOSAppInfo.InterfaceOrientation) { switch orientation { case .portrait(let condition): - self.init(enum: "portrait", subnodes: condition.map{ [SourceCodeFragment(from: $0)] }) + self.init(enum: "portrait", subnodes: condition.map { [SourceCodeFragment(from: $0)] }) case .portraitUpsideDown(let condition): - self.init(enum: "portraitUpsideDown", subnodes: condition.map{ [SourceCodeFragment(from: $0)] }) + self.init(enum: "portraitUpsideDown", subnodes: condition.map { [SourceCodeFragment(from: $0)] }) case .landscapeLeft(let condition): - self.init(enum: "landscapeLeft", subnodes: condition.map{ [SourceCodeFragment(from: $0)] }) + self.init(enum: "landscapeLeft", subnodes: condition.map { [SourceCodeFragment(from: $0)] }) case .landscapeRight(let condition): - self.init(enum: "landscapeRight", subnodes: condition.map{ [SourceCodeFragment(from: $0)] }) + self.init(enum: "landscapeRight", subnodes: condition.map { [SourceCodeFragment(from: $0)] }) } } @@ -866,11 +878,11 @@ fileprivate extension SourceCodeFragment { params.append(SourceCodeFragment(key: "allowsLocalNetworking", boolean: allowsLocalNetworking)) } if let exceptionDomains = configuration.exceptionDomains { - let subnodes = exceptionDomains.map{ SourceCodeFragment(from: $0) } + let subnodes = exceptionDomains.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "exceptionDomains", subnodes: subnodes)) } if let pinnedDomains = configuration.pinnedDomains { - let subnodes = pinnedDomains.map{ SourceCodeFragment(from: $0) } + let subnodes = pinnedDomains.map { SourceCodeFragment(from: $0) } params.append(SourceCodeFragment(key: "pinnedDomains", subnodes: subnodes)) } self.init(enum: "init", subnodes: params, multiline: true) @@ -906,16 +918,16 @@ fileprivate extension SourceCodeFragment { params.append(SourceCodeFragment(key: "includesSubdomains", boolean: includesSubdomains)) } if let pinnedCAIdentities = domain.pinnedCAIdentities { - let subnodes = pinnedCAIdentities.map{ SourceCodeFragment(stringPairs: $0.sorted{ $0.key < $1.key }.map{ ($0.key, $0.value) }) } + let subnodes = pinnedCAIdentities.map { SourceCodeFragment(stringPairs: $0.sorted { $0.key < $1.key }.map { ($0.key, $0.value) }) } params.append(SourceCodeFragment(key: "pinnedCAIdentities", subnodes: subnodes)) } if let pinnedLeafIdentities = domain.pinnedLeafIdentities { - let subnodes = pinnedLeafIdentities.map{ SourceCodeFragment(stringPairs: $0.sorted{ $0.key < $1.key }.map{ ($0.key, $0.value) }) } + let subnodes = pinnedLeafIdentities.map { SourceCodeFragment(stringPairs: $0.sorted { $0.key < $1.key }.map { ($0.key, $0.value) }) } params.append(SourceCodeFragment(key: "pinnedLeafIdentities", subnodes: subnodes)) } self.init(enum: "init", subnodes: params, multiline: true) } - + /// Instantiates a SourceCodeFragment from a single ProductSetting.IOSAppInfo.AppCategory. init(from appCategory: ProductSetting.IOSAppInfo.AppCategory) { switch appCategory.rawValue { @@ -1005,77 +1017,75 @@ fileprivate extension SourceCodeFragment { } } - /// Convenience initializers for key-value pairs of simple types. These make /// the logic above much simpler. public extension SourceCodeFragment { - + /// Initializes a SourceCodeFragment for a boolean in a generated manifest. init(key: String? = nil, boolean: Bool) { - let prefix = key.map{ $0 + ": " } ?? "" + let prefix = key.map { $0 + ": " } ?? "" self.init(prefix + (boolean ? "true" : "false")) } /// Initializes a SourceCodeFragment for an integer in a generated manifest. init(key: String? = nil, integer: Int) { - let prefix = key.map{ $0 + ": " } ?? "" + let prefix = key.map { $0 + ": " } ?? "" self.init(prefix + "\(integer)") } /// Initializes a SourceCodeFragment for a quoted string in a generated manifest. init(key: String? = nil, string: String) { - let prefix = key.map{ $0 + ": " } ?? "" + let prefix = key.map { $0 + ": " } ?? "" self.init(prefix + string.quotedForPackageManifest) } /// Initializes a SourceCodeFragment for an enum in a generated manifest. init(key: String? = nil, enum: String, string: String) { - let prefix = key.map{ $0 + ": " } ?? "" + let prefix = key.map { $0 + ": " } ?? "" let subnode = SourceCodeFragment(string: string) self.init(prefix + "." + `enum`, delimiters: .parentheses, multiline: false, subnodes: [subnode]) } /// Initializes a SourceCodeFragment for an enum in a generated manifest. init(key: String? = nil, enum: String, strings: [String]) { - let prefix = key.map{ $0 + ": " } ?? "" - let subnodes = strings.map{ SourceCodeFragment($0.quotedForPackageManifest) } + let prefix = key.map { $0 + ": " } ?? "" + let subnodes = strings.map { SourceCodeFragment($0.quotedForPackageManifest) } self.init(prefix + "." + `enum`, delimiters: .parentheses, multiline: false, subnodes: subnodes) } /// Initializes a SourceCodeFragment for an enum in a generated manifest. init(key: String? = nil, enum: String, subnodes: [SourceCodeFragment]? = nil, multiline: Bool = false) { - let prefix = key.map{ $0 + ": " } ?? "" + let prefix = key.map { $0 + ": " } ?? "" self.init(prefix + "." + `enum`, delimiters: .parentheses, multiline: multiline, subnodes: subnodes) } /// Initializes a SourceCodeFragment for a string list in a generated manifest. init(key: String? = nil, strings: [String], multiline: Bool = false) { - let prefix = key.map{ $0 + ": " } ?? "" - let subnodes = strings.map{ SourceCodeFragment($0.quotedForPackageManifest) } + let prefix = key.map { $0 + ": " } ?? "" + let subnodes = strings.map { SourceCodeFragment($0.quotedForPackageManifest) } self.init(prefix, delimiters: .brackets, multiline: multiline, subnodes: subnodes) } /// Initializes a SourceCodeFragment for a string map in a generated manifest. init(key: String? = nil, stringPairs: [(String, String)], multiline: Bool = false) { - let prefix = key.map{ $0 + ": " } ?? "" - let subnodes = stringPairs.isEmpty ? [SourceCodeFragment(":")] : stringPairs.map{ SourceCodeFragment($0.quotedForPackageManifest + ": " + $1.quotedForPackageManifest) } + let prefix = key.map { $0 + ": " } ?? "" + let subnodes = stringPairs.isEmpty ? [SourceCodeFragment(":")] : stringPairs.map { SourceCodeFragment($0.quotedForPackageManifest + ": " + $1.quotedForPackageManifest) } self.init(prefix, delimiters: .brackets, multiline: multiline, subnodes: subnodes) } /// Initializes a SourceCodeFragment for a node in a generated manifest. init(key: String? = nil, subnode: SourceCodeFragment) { - let prefix = key.map{ $0 + ": " } ?? "" + let prefix = key.map { $0 + ": " } ?? "" self.init(prefix, delimiters: .none, multiline: false, subnodes: [subnode]) } /// Initializes a SourceCodeFragment for a list of nodes in a generated manifest. init(key: String? = nil, subnodes: [SourceCodeFragment], multiline: Bool = true) { - let prefix = key.map{ $0 + ": " } ?? "" + let prefix = key.map { $0 + ": " } ?? "" self.init(prefix, delimiters: .brackets, multiline: multiline, subnodes: subnodes) } } - /// Helper type to emit source code. Represents one node of source code, as an /// arbitrary string followed by an optional child list, optionally enclosed in /// a pair of delimiters. @@ -1085,31 +1095,35 @@ public extension SourceCodeFragment { public struct SourceCodeFragment { /// A literal prefix to emit at the start of the source code fragment. var literal: String - + /// The type of delimiters to use around the subfragments (if any). var delimiters: Delimiters - + /// Whether or not to emit newlines before the subfragments (if any). var multiline: Bool - + /// Any subfragments; no delimiters are emitted if none. var subnodes: [SourceCodeFragment]? - + /// Type of delimiters to emit around any subfragments. public enum Delimiters { case none case brackets case parentheses } - - public init(_ literal: String, delimiters: Delimiters = .none, - multiline: Bool = true, subnodes: [SourceCodeFragment]? = nil) { + + public init( + _ literal: String, + delimiters: Delimiters = .none, + multiline: Bool = true, + subnodes: [SourceCodeFragment]? = nil + ) { self.literal = literal self.delimiters = delimiters self.multiline = multiline self.subnodes = subnodes } - + func generateSourceCode(indent: String = "") -> String { var string = literal if let subnodes { @@ -1123,7 +1137,7 @@ public struct SourceCodeFragment { for (idx, subnode) in subnodes.enumerated() { if multiline { string.append(subindent) } string.append(subnode.generateSourceCode(indent: subindent)) - if idx < subnodes.count-1 { + if idx < subnodes.count - 1 { string.append(multiline ? ",\n" : ", ") } } @@ -1143,7 +1157,8 @@ public struct SourceCodeFragment { extension Optional { fileprivate static func precedes( - _ a: Wrapped?, _ b: Wrapped?, + _ a: Wrapped?, + _ b: Wrapped?, compareWrapped: (Wrapped, Wrapped) -> Bool ) -> Bool { switch (a, b) { @@ -1221,7 +1236,8 @@ extension TargetBuildSettingDescription.Kind { extension String { fileprivate var quotedForPackageManifest: String { - return "\"" + self + return "\"" + + self .replacing("\\", with: "\\\\") .replacing("\"", with: "\\\"") + "\"" diff --git a/Sources/PackageModel/MinimumDeploymentTarget.swift b/Sources/PackageModel/MinimumDeploymentTarget.swift index d2510e323ce..dfd0380b29e 100644 --- a/Sources/PackageModel/MinimumDeploymentTarget.swift +++ b/Sources/PackageModel/MinimumDeploymentTarget.swift @@ -22,8 +22,8 @@ public struct MinimumDeploymentTarget { let platform: PackageModel.Platform } - private let minimumDeploymentTargets = ThreadSafeKeyValueStore() - private let xcTestMinimumDeploymentTargets = ThreadSafeKeyValueStore() + private let minimumDeploymentTargets = ThreadSafeKeyValueStore() + private let xcTestMinimumDeploymentTargets = ThreadSafeKeyValueStore() public static let `default`: MinimumDeploymentTarget = .init() @@ -72,13 +72,13 @@ public struct MinimumDeploymentTarget { // On macOS, we are determining the deployment target by looking at the XCTest binary. #if os(macOS) - do { - let runResult = try AsyncProcess.popen(arguments: ["/usr/bin/xcrun", "--sdk", sdkName, "--show-sdk-platform-path"]) + do { + let runResult = try AsyncProcess.popen(arguments: ["/usr/bin/xcrun", "--sdk", sdkName, "--show-sdk-platform-path"]) - if let version = try computeXCTestMinimumDeploymentTarget(with: runResult, platform: platform) { - return version - } - } catch { } // we do not treat this a fatal and instead use the fallback minimum deployment target + if let version = try computeXCTestMinimumDeploymentTarget(with: runResult, platform: platform) { + return version + } + } catch {} // we do not treat this a fatal and instead use the fallback minimum deployment target #endif return platform.oldestSupportedVersion @@ -101,7 +101,7 @@ private extension PackageModel.Platform { case .visionOS: return ("xros", "XROS") case .driverKit: - return nil // DriverKit does not support XCTest. + return nil // DriverKit does not support XCTest. default: return nil } diff --git a/Sources/PackageModel/Module/BinaryModule.swift b/Sources/PackageModel/Module/BinaryModule.swift index 31d47fbb948..4a7a14d18d1 100644 --- a/Sources/PackageModel/Module/BinaryModule.swift +++ b/Sources/PackageModel/Module/BinaryModule.swift @@ -21,7 +21,7 @@ public final class BinaryModule: Module { /// The kind of binary artifact. public let kind: Kind - + /// The original source of the binary artifact. public let origin: Origin @@ -63,7 +63,7 @@ public final class BinaryModule: Module { /// Artifact bundles containing static libraries. case artifactsArchive(types: [ArtifactsArchiveMetadata.ArtifactType]) - case unknown // for non-downloaded artifacts + case unknown // for non-downloaded artifacts public var fileExtension: String { switch self { diff --git a/Sources/PackageModel/Module/Module.swift b/Sources/PackageModel/Module/Module.swift index 7001c244212..213b22f8589 100644 --- a/Sources/PackageModel/Module/Module.swift +++ b/Sources/PackageModel/Module/Module.swift @@ -79,7 +79,6 @@ public class Module { /// A dependency referencing a product, with conditions. case product(_ product: ProductReference, conditions: [PackageCondition]) - @available(*, deprecated, renamed: "module") public var target: Module? { self.module } diff --git a/Sources/PackageModel/Module/PluginModule.swift b/Sources/PackageModel/Module/PluginModule.swift index ec180285b93..144ee6e75c9 100644 --- a/Sources/PackageModel/Module/PluginModule.swift +++ b/Sources/PackageModel/Module/PluginModule.swift @@ -60,7 +60,7 @@ public enum PluginCapability: Hashable { case .buildTool: self = .buildTool case .command(let intent, let permissions): - self = .command(intent: .init(from: intent), permissions: permissions.map{ .init(from: $0) }) + self = .command(intent: .init(from: intent), permissions: permissions.map { .init(from: $0) }) } } } diff --git a/Sources/PackageModel/Module/SwiftModule.swift b/Sources/PackageModel/Module/SwiftModule.swift index 1fbb2a257d4..30fa499c393 100644 --- a/Sources/PackageModel/Module/SwiftModule.swift +++ b/Sources/PackageModel/Module/SwiftModule.swift @@ -34,7 +34,8 @@ public final class SwiftModule: Module { packageAccess: Bool, testDiscoverySrc: Sources, buildSettings: BuildSettings.AssignmentTable = .init(), - implicit: Bool) { + implicit: Bool + ) { self.declaredSwiftVersions = [] super.init( @@ -145,9 +146,9 @@ public final class SwiftModule: Module { public var supportsTestableExecutablesFeature: Bool { // Exclude macros from testable executables if they are built as dylibs. #if BUILD_MACROS_AS_DYLIBS - return type == .executable || type == .snippet + return type == .executable || type == .snippet #else - return type == .executable || type == .macro || type == .snippet + return type == .executable || type == .macro || type == .snippet #endif } } diff --git a/Sources/PackageModel/ModuleMapType.swift b/Sources/PackageModel/ModuleMapType.swift index d4f1a241bee..230a0982c78 100644 --- a/Sources/PackageModel/ModuleMapType.swift +++ b/Sources/PackageModel/ModuleMapType.swift @@ -33,14 +33,11 @@ extension ModuleMapType: Codable { let container = try decoder.container(keyedBy: CodingKeys.self) if let path = try container.decodeIfPresent(AbsolutePath.self, forKey: .custom) { self = .custom(path) - } - else if let path = try container.decodeIfPresent(AbsolutePath.self, forKey: .umbrellaHeader) { + } else if let path = try container.decodeIfPresent(AbsolutePath.self, forKey: .umbrellaHeader) { self = .umbrellaHeader(path) - } - else if let path = try container.decodeIfPresent(AbsolutePath.self, forKey: .umbrellaDirectory) { + } else if let path = try container.decodeIfPresent(AbsolutePath.self, forKey: .umbrellaDirectory) { self = .umbrellaDirectory(path) - } - else { + } else { self = .none } } diff --git a/Sources/PackageModel/PackageIdentity.swift b/Sources/PackageModel/PackageIdentity.swift index bbc1b248694..930f43a9441 100644 --- a/Sources/PackageModel/PackageIdentity.swift +++ b/Sources/PackageModel/PackageIdentity.swift @@ -58,8 +58,8 @@ public struct PackageIdentity: CustomStringConvertible, Sendable { public var registry: RegistryIdentity? { let components = self.description.split(separator: ".", maxSplits: 1, omittingEmptySubsequences: true) guard components.count == 2, - let scope = Scope(components.first), - let name = Name(components.last) + let scope = Scope(components.first), + let name = Name(components.last) else { return .none } @@ -143,9 +143,7 @@ extension PackageIdentity { for (index, character) in zip(description.indices, description) { guard character.isASCII, - character.isLetter || - character.isNumber || - character == "-" + character.isLetter || character.isNumber || character == "-" else { throw StringError("A package scope consists of alphanumeric characters and hyphens.") } @@ -226,10 +224,7 @@ extension PackageIdentity { for (index, character) in zip(description.indices, description) { guard character.isASCII, - character.isLetter || - character.isNumber || - character == "-" || - character == "_" + character.isLetter || character.isNumber || character == "-" || character == "_" else { throw StringError("A package name consists of alphanumeric characters, underscores, and hyphens.") } @@ -318,9 +313,9 @@ struct PackageIdentityParser { /// Compute the default name of a package given its location. public static func computeDefaultName(fromLocation url: String) -> String { #if os(Windows) - let isSeparator: (Character) -> Bool = { $0 == "/" || $0 == "\\" } + let isSeparator: (Character) -> Bool = { $0 == "/" || $0 == "\\" } #else - let isSeparator: (Character) -> Bool = { $0 == "/" } + let isSeparator: (Character) -> Bool = { $0 == "/" } #endif // Get the last path component of the URL. @@ -332,7 +327,7 @@ struct PackageIdentityParser { let separatorIndex = url[.. (description: String, } #if os(Windows) -fileprivate let isSeparator: (Character) -> Bool = { $0 == "/" || $0 == "\\" } + fileprivate let isSeparator: (Character) -> Bool = { $0 == "/" || $0 == "\\" } #else -fileprivate let isSeparator: (Character) -> Bool = { $0 == "/" } + fileprivate let isSeparator: (Character) -> Bool = { $0 == "/" } #endif extension Character { @@ -527,8 +522,8 @@ extension String { @discardableResult fileprivate mutating func dropSchemeComponentPrefixIfPresent() -> String? { if let rangeOfDelimiter = range(of: "://"), - self[startIndex].isLetter, - self[.. (user: String, password: String?)? { if let indexOfAtSign = firstIndex(of: "@"), - let indexOfFirstPathComponent = firstIndex(where: isSeparator), - indexOfAtSign < indexOfFirstPathComponent + let indexOfFirstPathComponent = firstIndex(where: isSeparator), + indexOfAtSign < indexOfFirstPathComponent { defer { self.removeSubrange(...indexOfAtSign) } @@ -561,12 +556,12 @@ extension String { @discardableResult fileprivate mutating func removePortComponentIfPresent() -> Bool { if let indexOfFirstPathComponent = firstIndex(where: isSeparator), - let startIndexOfPort = firstIndex(of: ":"), - startIndexOfPort < endIndex, - let endIndexOfPort = self[index(after: startIndexOfPort)...].lastIndex(where: { $0.isDigit }), - endIndexOfPort <= indexOfFirstPathComponent + let startIndexOfPort = firstIndex(of: ":"), + startIndexOfPort < endIndex, + let endIndexOfPort = self[index(after: startIndexOfPort)...].lastIndex(where: { $0.isDigit }), + endIndexOfPort <= indexOfFirstPathComponent { - self.removeSubrange(startIndexOfPort ... endIndexOfPort) + self.removeSubrange(startIndexOfPort...endIndexOfPort) return true } diff --git a/Sources/PackageModel/PackageModel.swift b/Sources/PackageModel/PackageModel.swift index 2d96ae6b15e..2653fec3dbd 100644 --- a/Sources/PackageModel/PackageModel.swift +++ b/Sources/PackageModel/PackageModel.swift @@ -116,7 +116,7 @@ extension Package: CustomStringConvertible { } extension Package.Error: CustomStringConvertible { - public var description: String { + public var description: String { switch self { case .noManifest(let path, let version): var string = "\(path) has no Package.swift manifest" diff --git a/Sources/PackageModel/PackageReference.swift b/Sources/PackageModel/PackageReference.swift index ff6b448101c..349bfd645b1 100644 --- a/Sources/PackageModel/PackageReference.swift +++ b/Sources/PackageModel/PackageReference.swift @@ -155,7 +155,7 @@ public struct PackageReference { extension PackageReference: Equatable { // TODO: consider location as well? - public static func ==(lhs: PackageReference, rhs: PackageReference) -> Bool { + public static func == (lhs: PackageReference, rhs: PackageReference) -> Bool { return lhs.identity == rhs.identity } diff --git a/Sources/PackageModel/Platform.swift b/Sources/PackageModel/Platform.swift index 4f808aae187..710d5bcec92 100644 --- a/Sources/PackageModel/Platform.swift +++ b/Sources/PackageModel/Platform.swift @@ -51,7 +51,6 @@ public struct Platform: Equatable, Hashable, Codable, Sendable { public static let openbsd: Platform = Platform(name: "openbsd", oldestSupportedVersion: .unknown) public static let freebsd: Platform = Platform(name: "freebsd", oldestSupportedVersion: .unknown) - } /// Represents a platform supported by a target. diff --git a/Sources/PackageModel/Product.swift b/Sources/PackageModel/Product.swift index 4b5c79f696b..a50c58f6908 100644 --- a/Sources/PackageModel/Product.swift +++ b/Sources/PackageModel/Product.swift @@ -114,7 +114,6 @@ public enum ProductType: Equatable, Hashable, Sendable { } } - /// The products requested of a package. /// /// Any product which matches the filter will be used for dependency resolution, whereas unrequested products will be ignored. @@ -172,7 +171,6 @@ public enum ProductFilter: Equatable, Hashable, Sendable { } } - // MARK: - CustomStringConvertible extension Product: CustomStringConvertible { diff --git a/Sources/PackageModel/RegistryReleaseMetadata.swift b/Sources/PackageModel/RegistryReleaseMetadata.swift index 206f8f178f1..2d666eaf46a 100644 --- a/Sources/PackageModel/RegistryReleaseMetadata.swift +++ b/Sources/PackageModel/RegistryReleaseMetadata.swift @@ -14,7 +14,6 @@ import struct Basics.SourceControlURL import struct Foundation.URL import struct TSCUtility.Version - public struct RegistryReleaseMetadata: Hashable { public let source: Source public let metadata: Metadata @@ -110,7 +109,7 @@ public struct RegistryReleaseMetadata: Hashable { case recognized(type: String, commonName: String?, organization: String?, identity: String?) case unrecognized(commonName: String?, organization: String?) } - + /// Information about the source of the release. public enum Source: Hashable { case registry(URL) diff --git a/Sources/PackageModel/Resource.swift b/Sources/PackageModel/Resource.swift index 7e2b6c15e76..2476061ffd7 100644 --- a/Sources/PackageModel/Resource.swift +++ b/Sources/PackageModel/Resource.swift @@ -37,7 +37,7 @@ public struct Resource: Codable, Equatable { public init(rule: Rule, path: AbsolutePath) { var rule = rule if case .process(.some(let localization)) = rule, localization != "Base" { - rule = .process(localization: localization.lowercased()) + rule = .process(localization: localization.lowercased()) } self.rule = rule self.path = path diff --git a/Sources/PackageModel/Sanitizers.swift b/Sources/PackageModel/Sanitizers.swift index 0e17524ab9a..2e3684c6eba 100644 --- a/Sources/PackageModel/Sanitizers.swift +++ b/Sources/PackageModel/Sanitizers.swift @@ -21,11 +21,11 @@ public enum Sanitizer: String, Encodable, CaseIterable { /// Return an established short name for a sanitizer, e.g. "asan". public var shortName: String { switch self { - case .address: return "asan" - case .thread: return "tsan" - case .undefined: return "ubsan" - case .scudo: return "scudo" - case .fuzzer: return "fuzzer" + case .address: return "asan" + case .thread: return "tsan" + case .undefined: return "ubsan" + case .scudo: return "scudo" + case .fuzzer: return "fuzzer" } } } @@ -67,6 +67,6 @@ public struct EnabledSanitizers: Encodable { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(sanitizers.sorted{ $0.rawValue < $1.rawValue }, forKey: .sanitizers) + try container.encode(sanitizers.sorted { $0.rawValue < $1.rawValue }, forKey: .sanitizers) } } diff --git a/Sources/PackageModel/Snippets/Parsing/PlainTextSnippetExtractor.swift b/Sources/PackageModel/Snippets/Parsing/PlainTextSnippetExtractor.swift index 25b87cebce3..b586f6f99c8 100644 --- a/Sources/PackageModel/Snippets/Parsing/PlainTextSnippetExtractor.swift +++ b/Sources/PackageModel/Snippets/Parsing/PlainTextSnippetExtractor.swift @@ -64,20 +64,26 @@ fileprivate extension String { /// without changing the relative indentation between lines. This is /// useful for re-indenting some inner part of a block of nested code. mutating func trimExtraIndentation() { - var lines = self.split(separator: "\n", maxSplits: Int.max, - omittingEmptySubsequences: false) - lines = Array(lines - .drop(while: { $0.isEmptyOrWhiteSpace }) - .reversed() - .drop(while: { $0.isEmptyOrWhiteSpace }) - .reversed()) - - let minimumIndentation = lines.map { - guard !$0.isEmpty else { - return Int.max - } - return $0.prefix { $0 == " " }.count - }.min() ?? 0 + var lines = self.split( + separator: "\n", + maxSplits: Int.max, + omittingEmptySubsequences: false + ) + lines = Array( + lines + .drop(while: { $0.isEmptyOrWhiteSpace }) + .reversed() + .drop(while: { $0.isEmptyOrWhiteSpace }) + .reversed() + ) + + let minimumIndentation = + lines.map { + guard !$0.isEmpty else { + return Int.max + } + return $0.prefix { $0 == " " }.count + }.min() ?? 0 guard minimumIndentation > 0 else { return @@ -116,7 +122,8 @@ struct PlainTextSnippetExtractor { } if var comment = line.parsedLineCommentText, - comment.starts(with: "!") { + comment.starts(with: "!") + { comment.removeFirst(1) comment = comment.drop { $0.isWhitespace } if lastExplanationLine.isEmptyOrWhiteSpace && comment.isEmptyOrWhiteSpace { @@ -137,7 +144,7 @@ struct PlainTextSnippetExtractor { self.presentationCode .removeLeadingAndTrailingNewlines() - + self.presentationCode .trimExtraIndentation() } diff --git a/Sources/PackageModel/SwiftLanguageVersion.swift b/Sources/PackageModel/SwiftLanguageVersion.swift index f041e943544..e10d0d686d6 100644 --- a/Sources/PackageModel/SwiftLanguageVersion.swift +++ b/Sources/PackageModel/SwiftLanguageVersion.swift @@ -36,12 +36,12 @@ public struct SwiftLanguageVersion: Hashable, Sendable { /// The list of known Swift language versions. public static let knownSwiftLanguageVersions = [ - v3, v4, v4_2, v5, v6 + v3, v4, v4_2, v5, v6, ] /// The list of supported Swift language versions for this toolchain. public static let supportedSwiftLanguageVersions = [ - v4, v4_2, v5, v6 + v4, v4_2, v5, v6, ] /// The raw value of the language version. diff --git a/Sources/PackageModel/SwiftSDKs/SwiftSDK.swift b/Sources/PackageModel/SwiftSDKs/SwiftSDK.swift index bef655063af..50ba194f4f4 100644 --- a/Sources/PackageModel/SwiftSDKs/SwiftSDK.swift +++ b/Sources/PackageModel/SwiftSDKs/SwiftSDK.swift @@ -63,8 +63,8 @@ public enum SwiftSDKError: Swift.Error { case swiftSDKArtifactAlreadyInstalled(installedBundleName: String, newBundleName: String, artifactID: String) #if os(macOS) - /// Quarantine attribute should be removed by the `xattr` command from an installed bundle. - case quarantineAttributePresent(bundlePath: Basics.AbsolutePath) + /// Quarantine attribute should be removed by the `xattr` command from an installed bundle. + case quarantineAttributePresent(bundlePath: Basics.AbsolutePath) #endif } @@ -73,20 +73,20 @@ extension SwiftSDKError: CustomStringConvertible { switch self { case let .checksumInvalid(computed, provided): return """ - Computed archive checksum `\(computed)` does not match the provided checksum `\(provided)`. - """ + Computed archive checksum `\(computed)` does not match the provided checksum `\(provided)`. + """ case .checksumNotProvided(let url): return """ - Bundles installed from remote URLs (`\(url)`) require their checksum passed via `--checksum` option. - The distributor of the bundle must compute it with the `swift package compute-checksum` \ - command and provide it with their Swift SDK installation instructions. - """ + Bundles installed from remote URLs (`\(url)`) require their checksum passed via `--checksum` option. + The distributor of the bundle must compute it with the `swift package compute-checksum` \ + command and provide it with their Swift SDK installation instructions. + """ case .invalidBundleArchive(let archivePath): return """ - Swift SDK archive at `\(archivePath)` does not contain at least one directory with the \ - `.artifactbundle` extension. - """ + Swift SDK archive at `\(archivePath)` does not contain at least one directory with the \ + `.artifactbundle` extension. + """ case .invalidPathOrURL(let argument): return "`\(argument)` is neither a valid filesystem path nor a URL." case .invalidSchemaVersion: @@ -95,50 +95,50 @@ extension SwiftSDKError: CustomStringConvertible { return problem case .invalidBundleName(let name): return """ - invalid bundle name `\(name)`, unpacked Swift SDK bundles are expected to have `.artifactbundle` extension - """ + invalid bundle name `\(name)`, unpacked Swift SDK bundles are expected to have `.artifactbundle` extension + """ case .noSwiftSDKDecoded(let path): return "no valid Swift SDKs were decoded from a metadata file at path `\(path)`" case .pathIsNotDirectory(let path): return "path expected to be a directory is not a directory or doesn't exist: `\(path)`" case .unserializableMetadata: return """ - Swift SDK configuration couldn't be serialized with the latest serialization schema, potentially because \ - it was deserialized from an earlier incompatible schema version or initialized manually with missing \ - properties required for initialization - """ + Swift SDK configuration couldn't be serialized with the latest serialization schema, potentially because \ + it was deserialized from an earlier incompatible schema version or initialized manually with missing \ + properties required for initialization + """ case .swiftSDKNotFound(let artifactID, let hostTriple, let targetTriple): if let targetTriple { return """ - Swift SDK with ID `\(artifactID)`, host triple \(hostTriple), and target triple \(targetTriple) is not \ - currently installed. - """ + Swift SDK with ID `\(artifactID)`, host triple \(hostTriple), and target triple \(targetTriple) is not \ + currently installed. + """ } else { return """ - Swift SDK with ID `\(artifactID)` is not currently installed. - """ + Swift SDK with ID `\(artifactID)` is not currently installed. + """ } case .swiftSDKBundleAlreadyInstalled(let bundleName): return """ - Swift SDK bundle with name `\(bundleName)` is already installed. Can't install a new bundle \ - with the same name. - """ + Swift SDK bundle with name `\(bundleName)` is already installed. Can't install a new bundle \ + with the same name. + """ case .swiftSDKArtifactAlreadyInstalled(let installedBundleName, let newBundleName, let artifactID): return """ - A Swift SDK with artifact ID `\(artifactID)` is already included in an installed bundle with name \ - `\(installedBundleName)`. Can't install a new bundle `\(newBundleName)` with this artifact, artifact IDs \ - are expected to be unique across all installed Swift SDK bundles. - """ + A Swift SDK with artifact ID `\(artifactID)` is already included in an installed bundle with name \ + `\(installedBundleName)`. Can't install a new bundle `\(newBundleName)` with this artifact, artifact IDs \ + are expected to be unique across all installed Swift SDK bundles. + """ #if os(macOS) - case .quarantineAttributePresent(let bundlePath): - return """ - Quarantine attribute is present on a Swift SDK bundle at path `\(bundlePath)`. If you're certain that the \ - bundle was downloaded from a trusted source, you can remove the attribute with this command: + case .quarantineAttributePresent(let bundlePath): + return """ + Quarantine attribute is present on a Swift SDK bundle at path `\(bundlePath)`. If you're certain that the \ + bundle was downloaded from a trusted source, you can remove the attribute with this command: - xattr -d -r -s com.apple.quarantine "\(bundlePath)" + xattr -d -r -s com.apple.quarantine "\(bundlePath)" - and try to install this bundle again. - """ + and try to install this bundle again. + """ #endif } } @@ -336,7 +336,7 @@ public struct SwiftSDK: Equatable { /// - properties: properties of a Swift SDK for the given triple. /// - swiftSDKDirectory: directory used for converting relative paths in `properties` to absolute paths. fileprivate init( - _ properties: SwiftSDKMetadataV4.TripleProperties, + _ properties: SwiftSDKMetadataV4.TripleProperties, swiftSDKDirectory: Basics.AbsolutePath? = nil ) throws where Path == Basics.AbsolutePath { self.init( @@ -565,25 +565,25 @@ public struct SwiftSDK: Equatable { let sdkPath: Basics.AbsolutePath? #if os(macOS) - let darwinPlatform = darwinPlatformOverride ?? .macOS - // Get the SDK. - if let value = environment["SDKROOT"] { - sdkPath = try AbsolutePath(validating: value) - } else if let value = environment[EnvironmentKey("SWIFTPM_SDKROOT_\(darwinPlatform.xcrunName)")] { - sdkPath = try AbsolutePath(validating: value) - } else { - // No value in env, so search for it. - let sdkPathStr = try AsyncProcess.checkNonZeroExit( - arguments: ["/usr/bin/xcrun", "--sdk", darwinPlatform.xcrunName, "--show-sdk-path"], - environment: environment - ).spm_chomp() - guard !sdkPathStr.isEmpty else { - throw SwiftSDKError.invalidInstallation("default SDK not found") + let darwinPlatform = darwinPlatformOverride ?? .macOS + // Get the SDK. + if let value = environment["SDKROOT"] { + sdkPath = try AbsolutePath(validating: value) + } else if let value = environment[EnvironmentKey("SWIFTPM_SDKROOT_\(darwinPlatform.xcrunName)")] { + sdkPath = try AbsolutePath(validating: value) + } else { + // No value in env, so search for it. + let sdkPathStr = try AsyncProcess.checkNonZeroExit( + arguments: ["/usr/bin/xcrun", "--sdk", darwinPlatform.xcrunName, "--show-sdk-path"], + environment: environment + ).spm_chomp() + guard !sdkPathStr.isEmpty else { + throw SwiftSDKError.invalidInstallation("default SDK not found") + } + sdkPath = try AbsolutePath(validating: sdkPathStr) } - sdkPath = try AbsolutePath(validating: sdkPathStr) - } #else - sdkPath = nil + sdkPath = nil #endif // Compute common arguments for clang and swift. @@ -591,22 +591,22 @@ public struct SwiftSDK: Equatable { var extraCCFlags: [String] = [] var extraSwiftCFlags: [String] = [] #if os(macOS) - do { - let sdkPaths = try SwiftSDK.sdkPlatformPaths(for: darwinPlatform, environment: environment) - extraCCFlags.append(contentsOf: sdkPaths.frameworks.flatMap { ["-F", $0.pathString] }) - extraSwiftCFlags.append(contentsOf: sdkPaths.frameworks.flatMap { ["-F", $0.pathString] }) - extraSwiftCFlags.append(contentsOf: sdkPaths.libraries.flatMap { ["-I", $0.pathString] }) - extraSwiftCFlags.append(contentsOf: sdkPaths.libraries.flatMap { ["-L", $0.pathString] }) - xctestSupport = .supported - } catch { - xctestSupport = .unsupported(reason: String(describing: error)) - } + do { + let sdkPaths = try SwiftSDK.sdkPlatformPaths(for: darwinPlatform, environment: environment) + extraCCFlags.append(contentsOf: sdkPaths.frameworks.flatMap { ["-F", $0.pathString] }) + extraSwiftCFlags.append(contentsOf: sdkPaths.frameworks.flatMap { ["-F", $0.pathString] }) + extraSwiftCFlags.append(contentsOf: sdkPaths.libraries.flatMap { ["-I", $0.pathString] }) + extraSwiftCFlags.append(contentsOf: sdkPaths.libraries.flatMap { ["-L", $0.pathString] }) + xctestSupport = .supported + } catch { + xctestSupport = .unsupported(reason: String(describing: error)) + } #else - xctestSupport = .supported + xctestSupport = .supported #endif #if !os(Windows) - extraCCFlags += ["-fPIC"] + extraCCFlags += ["-fPIC"] #endif return SwiftSDK( @@ -658,12 +658,14 @@ public struct SwiftSDK: Equatable { if let path = _sdkPlatformFrameworkPath[darwinPlatform] { return path } - let platformPath = try environment[ - EnvironmentKey("SWIFTPM_PLATFORM_PATH_\(darwinPlatform.xcrunName)") - ] ?? AsyncProcess.checkNonZeroExit( - arguments: ["/usr/bin/xcrun", "--sdk", darwinPlatform.xcrunName, "--show-sdk-platform-path"], - environment: environment - ).spm_chomp() + let platformPath = + try environment[ + EnvironmentKey("SWIFTPM_PLATFORM_PATH_\(darwinPlatform.xcrunName)") + ] + ?? AsyncProcess.checkNonZeroExit( + arguments: ["/usr/bin/xcrun", "--sdk", darwinPlatform.xcrunName, "--show-sdk-platform-path"], + environment: environment + ).spm_chomp() guard !platformPath.isEmpty else { throw StringError("could not determine SDK platform path") @@ -671,15 +673,21 @@ public struct SwiftSDK: Equatable { // For testing frameworks. let frameworksPath = try Basics.AbsolutePath(validating: platformPath).appending( - components: "Developer", "Library", "Frameworks" + components: "Developer", + "Library", + "Frameworks" ) let privateFrameworksPath = try Basics.AbsolutePath(validating: platformPath).appending( - components: "Developer", "Library", "PrivateFrameworks" + components: "Developer", + "Library", + "PrivateFrameworks" ) // For testing libraries. let librariesPath = try Basics.AbsolutePath(validating: platformPath).appending( - components: "Developer", "usr", "lib" + components: "Developer", + "usr", + "lib" ) let sdkPlatformFrameworkPath = PlatformPaths(frameworks: [frameworksPath, privateFrameworksPath], libraries: [librariesPath]) @@ -703,16 +711,16 @@ public struct SwiftSDK: Equatable { environment: Environment = .current ) -> SwiftSDK? { #if os(macOS) - if let darwinPlatform = targetTriple.darwinPlatform { - // the Darwin SDKs are trivially available on macOS - var sdk = try? self.systemSwiftSDK( - hostSDK.toolset.rootPaths.first, - environment: environment, - darwinPlatformOverride: darwinPlatform - ) - sdk?.targetTriple = targetTriple - return sdk - } + if let darwinPlatform = targetTriple.darwinPlatform { + // the Darwin SDKs are trivially available on macOS + var sdk = try? self.systemSwiftSDK( + hostSDK.toolset.rootPaths.first, + environment: environment, + darwinPlatformOverride: darwinPlatform + ) + sdk?.targetTriple = targetTriple + return sdk + } #endif return nil @@ -720,18 +728,18 @@ public struct SwiftSDK: Equatable { /// Computes the target Swift SDK for the given options. public static func deriveTargetSwiftSDK( - hostSwiftSDK: SwiftSDK, - hostTriple: Triple, - customToolsets: [Basics.AbsolutePath] = [], - customCompileDestination: Basics.AbsolutePath? = nil, - customCompileTriple: Triple? = nil, - customCompileToolchain: Basics.AbsolutePath? = nil, - customCompileSDK: Basics.AbsolutePath? = nil, - swiftSDKSelector: String? = nil, - architectures: [String] = [], - store: SwiftSDKBundleStore, - observabilityScope: ObservabilityScope, - fileSystem: FileSystem + hostSwiftSDK: SwiftSDK, + hostTriple: Triple, + customToolsets: [Basics.AbsolutePath] = [], + customCompileDestination: Basics.AbsolutePath? = nil, + customCompileTriple: Triple? = nil, + customCompileToolchain: Basics.AbsolutePath? = nil, + customCompileSDK: Basics.AbsolutePath? = nil, + swiftSDKSelector: String? = nil, + architectures: [String] = [], + store: SwiftSDKBundleStore, + observabilityScope: ObservabilityScope, + fileSystem: FileSystem ) throws -> SwiftSDK { var swiftSDK: SwiftSDK var isBasedOnHostSDK: Bool = false @@ -747,15 +755,15 @@ public struct SwiftSDK: Equatable { if swiftSDKs.count == 1 { swiftSDK = swiftSDKs[0] } else if swiftSDKs.count > 1, - let triple = customCompileTriple, - let matchingSDK = swiftSDKs.first(where: { $0.targetTriple == triple }) + let triple = customCompileTriple, + let matchingSDK = swiftSDKs.first(where: { $0.targetTriple == triple }) { swiftSDK = matchingSDK } else { throw SwiftSDKError.noSwiftSDKDecoded(customDestination) } } else if let targetTriple = customCompileTriple, - let targetSwiftSDK = SwiftSDK.defaultSwiftSDK(for: targetTriple, hostSDK: hostSwiftSDK) + let targetSwiftSDK = SwiftSDK.defaultSwiftSDK(for: targetTriple, hostSDK: hostSwiftSDK) { swiftSDK = targetSwiftSDK } else if let swiftSDKSelector { @@ -765,7 +773,8 @@ public struct SwiftSDK: Equatable { // If a user-installed bundle for the selector doesn't exist, check if the // selector is recognized as a default SDK. if let targetTriple = try? Triple(swiftSDKSelector), - let defaultSDK = SwiftSDK.defaultSwiftSDK(for: targetTriple, hostSDK: hostSwiftSDK) { + let defaultSDK = SwiftSDK.defaultSwiftSDK(for: targetTriple, hostSDK: hostSwiftSDK) + { swiftSDK = defaultSDK } else { throw error @@ -908,11 +917,12 @@ extension SwiftSDK { let triple = try Triple(triple) let pathStrings = properties.toolsetPaths ?? [] - let defaultTools: [Toolset.KnownTool: Toolset.ToolProperties] = if triple.isWasm { - [.debugger: wasmKitProperties, .testRunner: wasmKitProperties] - } else { - [:] - } + let defaultTools: [Toolset.KnownTool: Toolset.ToolProperties] = + if triple.isWasm { + [.debugger: wasmKitProperties, .testRunner: wasmKitProperties] + } else { + [:] + } let toolset = try pathStrings.reduce(into: Toolset(knownTools: defaultTools, rootPaths: [])) { try $0.merge( with: Toolset( @@ -938,11 +948,12 @@ extension SwiftSDK { return try swiftSDKs.targetTriples.map { triple, properties in let triple = try Triple(triple) - let defaultTools: [Toolset.KnownTool: Toolset.ToolProperties] = if triple.isWasm { - [.debugger: wasmKitProperties, .testRunner: wasmKitProperties] - } else { - [:] - } + let defaultTools: [Toolset.KnownTool: Toolset.ToolProperties] = + if triple.isWasm { + [.debugger: wasmKitProperties, .testRunner: wasmKitProperties] + } else { + [:] + } let pathStrings = properties.toolsetPaths ?? [] let toolset = try pathStrings.reduce(into: Toolset(knownTools: defaultTools, rootPaths: [])) { try $0.merge( @@ -1015,7 +1026,7 @@ extension SwiftSDK { switch version.version { case 1: let serializedMetadata = try decoder.decode( - path: path, + path: path, fileSystem: fileSystem, as: SerializedDestinationV1.self ) @@ -1068,7 +1079,7 @@ extension SwiftSDK { guard let targetTriple = self.targetTriple, let sdkRootDir = self.pathsConfiguration.sdkRootPath else { throw SwiftSDKError.unserializableMetadata } - + return ( targetTriple, .init( diff --git a/Sources/PackageModel/SwiftSDKs/SwiftSDKBundle.swift b/Sources/PackageModel/SwiftSDKs/SwiftSDKBundle.swift index a353c08ba53..b474ab41717 100644 --- a/Sources/PackageModel/SwiftSDKs/SwiftSDKBundle.swift +++ b/Sources/PackageModel/SwiftSDKs/SwiftSDKBundle.swift @@ -99,13 +99,13 @@ extension [SwiftSDKBundle] { if let matchedByID { observabilityScope.emit( warning: - """ - multiple Swift SDKs match ID `\(artifactID)` and host triple \( + """ + multiple Swift SDKs match ID `\(artifactID)` and host triple \( hostTriple.tripleString - ), selected one at \( + ), selected one at \( matchedByID.path.appending(matchedByID.variant.metadata.path) - ) - """ + ) + """ ) } else { matchedByID = (bundle.path, variant, swiftSDK) @@ -116,13 +116,13 @@ extension [SwiftSDKBundle] { if let matchedByTriple { observabilityScope.emit( warning: - """ - multiple Swift SDKs match target triple `\(selector)` and host triple \( + """ + multiple Swift SDKs match target triple `\(selector)` and host triple \( hostTriple.tripleString - ), selected one at \( + ), selected one at \( matchedByTriple.path.appending(matchedByTriple.variant.metadata.path) - ) - """ + ) + """ ) } else { matchedByTriple = (bundle.path, variant, swiftSDK) @@ -136,11 +136,11 @@ extension [SwiftSDKBundle] { if let matchedByID, let matchedByTriple, matchedByID != matchedByTriple { observabilityScope.emit( warning: - """ - multiple Swift SDKs match the query `\(selector)` and host triple \( + """ + multiple Swift SDKs match the query `\(selector)` and host triple \( hostTriple.tripleString - ), selected one at \(matchedByID.path.appending(matchedByID.variant.metadata.path)) - """ + ), selected one at \(matchedByID.path.appending(matchedByID.variant.metadata.path)) + """ ) } diff --git a/Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift b/Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift index 5b506feba78..2ec19079dd9 100644 --- a/Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift +++ b/Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift @@ -11,8 +11,7 @@ //===----------------------------------------------------------------------===// // FIXME: can't write `import actor Basics.HTTPClient`, importing the whole module because of that :( -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import struct Foundation.URL import protocol TSCBasic.FileSystem import struct TSCBasic.RegEx @@ -52,10 +51,10 @@ public final class SwiftSDKBundleStore { switch self { case let .noMatchingSwiftSDK(selector, hostTriple): return """ - No Swift SDK found matching query `\(selector)` and host triple \ - `\(hostTriple.tripleString)`. Use `swift sdk list` command to see \ - available Swift SDKs. - """ + No Swift SDK found matching query `\(selector)` and host triple \ + `\(hostTriple.tripleString)`. Use `swift sdk list` command to see \ + available Swift SDKs. + """ } } } @@ -136,11 +135,13 @@ public final class SwiftSDKBundleStore { ) } - guard var selectedSwiftSDKs = validBundles.selectSwiftSDK( - matching: selector, - hostTriple: hostTriple, - observabilityScope: self.observabilityScope - ) else { + guard + var selectedSwiftSDKs = validBundles.selectSwiftSDK( + matching: selector, + hostTriple: hostTriple, + observabilityScope: self.observabilityScope + ) + else { throw Error.noMatchingSwiftSDK(selector: selector, hostTriple: hostTriple) } @@ -164,8 +165,7 @@ public final class SwiftSDKBundleStore { let bundleName = try await withTemporaryDirectory(fileSystem: self.fileSystem, removeTreeOnDeinit: true) { temporaryDirectory in let bundlePath: AbsolutePath - if - let bundleURL = URL(string: bundlePathOrURL), + if let bundleURL = URL(string: bundlePathOrURL), let scheme = bundleURL.scheme, scheme == "http" || scheme == "https" { @@ -202,9 +202,9 @@ public final class SwiftSDKBundleStore { let step = step > Int.max ? Int.max : Int(step) let total = total.map { $0 > Int.max ? Int.max : Int($0) } ?? step progressAnimation.update( - step: step, - total: total, - text: "Downloading \(bundleURL.lastPathComponent)" + step: step, + total: total, + text: "Downloading \(bundleURL.lastPathComponent)" ) } ) @@ -220,8 +220,7 @@ public final class SwiftSDKBundleStore { self.outputHandler(.checksumValid) bundlePath = downloadedBundlePath - } else if - let cwd: AbsolutePath = self.fileSystem.currentWorkingDirectory, + } else if let cwd: AbsolutePath = self.fileSystem.currentWorkingDirectory, let originalBundlePath = try? AbsolutePath(validating: bundlePathOrURL, relativeTo: cwd) { bundlePath = originalBundlePath @@ -264,10 +263,11 @@ public final class SwiftSDKBundleStore { try await archiver.extract(from: bundlePath, to: extractionResultsDirectory) - guard let bundleName = try fileSystem.getDirectoryContents(extractionResultsDirectory).first(where: { - $0.hasSuffix(".\(artifactBundleExtension)") && - fileSystem.isDirectory(extractionResultsDirectory.appending($0)) - }) else { + guard + let bundleName = try fileSystem.getDirectoryContents(extractionResultsDirectory).first(where: { + $0.hasSuffix(".\(artifactBundleExtension)") && fileSystem.isDirectory(extractionResultsDirectory.appending($0)) + }) + else { throw SwiftSDKError.invalidBundleArchive(bundlePath) } @@ -292,10 +292,10 @@ public final class SwiftSDKBundleStore { archiver: any Archiver ) async throws -> String { #if os(macOS) - // Check the quarantine attribute on bundles downloaded manually in the browser. - guard !self.fileSystem.hasAttribute(.quarantine, validatedBundlePath) else { - throw SwiftSDKError.quarantineAttributePresent(bundlePath: validatedBundlePath) - } + // Check the quarantine attribute on bundles downloaded manually in the browser. + guard !self.fileSystem.hasAttribute(.quarantine, validatedBundlePath) else { + throw SwiftSDKError.quarantineAttributePresent(bundlePath: validatedBundlePath) + } #endif let unpackedBundlePath = try await self.unpackIfNeeded( @@ -364,9 +364,9 @@ public final class SwiftSDKBundleStore { if artifactMetadata.type == .crossCompilationDestination { self.observabilityScope.emit( warning: """ - `crossCompilationDestination` bundle metadata value used for `\(artifactID)` is deprecated, \ - use `swiftSDK` instead. - """ + `crossCompilationDestination` bundle metadata value used for `\(artifactID)` is deprecated, \ + use `swiftSDK` instead. + """ ) } else { guard artifactMetadata.type == .swiftSDK else { continue } @@ -375,11 +375,11 @@ public final class SwiftSDKBundleStore { var variants = [SwiftSDKBundle.Variant]() for variantMetadata in artifactMetadata.variants { - var variantConfigurationPath = bundlePath + var variantConfigurationPath = + bundlePath .appending(variantMetadata.path) - if variantConfigurationPath.extension != ".json" && - self.fileSystem.isDirectory(variantConfigurationPath) { + if variantConfigurationPath.extension != ".json" && self.fileSystem.isDirectory(variantConfigurationPath) { variantConfigurationPath = variantConfigurationPath.appending("swift-sdk.json") } diff --git a/Sources/PackageModel/SwiftSDKs/SwiftSDKConfigurationStore.swift b/Sources/PackageModel/SwiftSDKs/SwiftSDKConfigurationStore.swift index 6f446551233..4609c3260fb 100644 --- a/Sources/PackageModel/SwiftSDKs/SwiftSDKConfigurationStore.swift +++ b/Sources/PackageModel/SwiftSDKs/SwiftSDKConfigurationStore.swift @@ -111,11 +111,13 @@ public final class SwiftSDKConfigurationStore { let swiftSDKs = try self.swiftSDKBundleStore.allValidBundles - guard var swiftSDK = swiftSDKs.selectSwiftSDK( - id: sdkID, - hostTriple: nil, - targetTriple: targetTriple - ) else { + guard + var swiftSDK = swiftSDKs.selectSwiftSDK( + id: sdkID, + hostTriple: nil, + targetTriple: targetTriple + ) + else { return nil } @@ -190,10 +192,12 @@ public final class SwiftSDKConfigurationStore { } for targetTriple in targetTriples { - guard let swiftSDK = try self.readConfiguration( - sdkID: sdkID, - targetTriple: targetTriple - ) else { + guard + let swiftSDK = try self.readConfiguration( + sdkID: sdkID, + targetTriple: targetTriple + ) + else { throw SwiftSDKError.swiftSDKNotFound( artifactID: sdkID, hostTriple: hostTriple, @@ -214,9 +218,9 @@ public final class SwiftSDKConfigurationStore { } else { swiftSDKBundleStore.observabilityScope.emit( info: """ - All configuration properties of Swift SDK `\(sdkID)` for target triple \ - `\(targetTriple)` were successfully reset. - """ + All configuration properties of Swift SDK `\(sdkID)` for target triple \ + `\(targetTriple)` were successfully reset. + """ ) } } else { @@ -226,9 +230,9 @@ public final class SwiftSDKConfigurationStore { guard !updatedProperties.isEmpty else { swiftSDKBundleStore.observabilityScope.emit( error: """ - No properties of Swift SDK `\(sdkID)` for target triple `\(targetTriple)` were updated \ - since none were specified. Pass `--help` flag to see the list of all available properties. - """ + No properties of Swift SDK `\(sdkID)` for target triple `\(targetTriple)` were updated \ + since none were specified. Pass `--help` flag to see the list of all available properties. + """ ) return false } @@ -240,9 +244,9 @@ public final class SwiftSDKConfigurationStore { swiftSDKBundleStore.observabilityScope.emit( info: """ - These properties of Swift SDK `\(sdkID)` for target triple \ - `\(targetTriple)` were successfully updated: \(updatedProperties.joined(separator: ", ")). - """ + These properties of Swift SDK `\(sdkID)` for target triple \ + `\(targetTriple)` were successfully updated: \(updatedProperties.joined(separator: ", ")). + """ ) } diff --git a/Sources/PackageModel/Toolchain+SupportedFeatures.swift b/Sources/PackageModel/Toolchain+SupportedFeatures.swift index 924fa395737..c236b1302f8 100644 --- a/Sources/PackageModel/Toolchain+SupportedFeatures.swift +++ b/Sources/PackageModel/Toolchain+SupportedFeatures.swift @@ -44,8 +44,8 @@ public enum SwiftCompilerFeature { public var name: String { switch self { case .optional(name: let name, migratable: _, categories: _, flagName: _), - .upcoming(name: let name, migratable: _, categories: _, enabledIn: _), - .experimental(name: let name, migratable: _, categories: _): + .upcoming(name: let name, migratable: _, categories: _, enabledIn: _), + .experimental(name: let name, migratable: _, categories: _): name } } @@ -53,8 +53,8 @@ public enum SwiftCompilerFeature { public var migratable: Bool { switch self { case .optional(name: _, migratable: let migratable, categories: _, flagName: _), - .upcoming(name: _, migratable: let migratable, categories: _, enabledIn: _), - .experimental(name: _, migratable: let migratable, categories: _): + .upcoming(name: _, migratable: let migratable, categories: _, enabledIn: _), + .experimental(name: _, migratable: let migratable, categories: _): migratable } } @@ -62,8 +62,8 @@ public enum SwiftCompilerFeature { public var categories: [String] { switch self { case .optional(name: _, migratable: _, categories: let categories, flagName: _), - .upcoming(name: _, migratable: _, categories: let categories, enabledIn: _), - .experimental(name: _, migratable: _, categories: let categories): + .upcoming(name: _, migratable: _, categories: let categories, enabledIn: _), + .experimental(name: _, migratable: _, categories: let categories): categories } } @@ -122,11 +122,12 @@ extension Toolchain { let name: String = try $0.get("name") let categories: [String]? = try $0.getArrayIfAvailable("categories") let migratable: Bool? = $0.get("migratable") - let enabledIn = if let version = try? $0.get(String.self, forKey: "enabled_in") { - version - } else { - try String($0.get(Int.self, forKey: "enabled_in")) - } + let enabledIn = + if let version = try? $0.get(String.self, forKey: "enabled_in") { + version + } else { + try String($0.get(Int.self, forKey: "enabled_in")) + } guard let mode = SwiftLanguageVersion(string: enabledIn) else { throw InternalError("Unknown swift language mode: \(enabledIn)") diff --git a/Sources/PackageModel/Toolchain.swift b/Sources/PackageModel/Toolchain.swift index fb2fbce9f17..4d63791895c 100644 --- a/Sources/PackageModel/Toolchain.swift +++ b/Sources/PackageModel/Toolchain.swift @@ -54,7 +54,7 @@ public protocol Toolchain { // the OSS clang compiler. This API should not used for any other purpose. /// Returns true if clang compiler's vendor is Apple and nil if unknown. func _isClangCompilerVendorApple() throws -> Bool? - + /// Additional flags to be passed to the build tools. var extraFlags: BuildFlags { get } @@ -100,22 +100,22 @@ extension Toolchain { switch os { case .windows: return compilerPath - .parentDirectory // bin - .parentDirectory // usr - .parentDirectory // - .parentDirectory // Toolchains - .parentDirectory // + .parentDirectory // bin + .parentDirectory // usr + .parentDirectory // + .parentDirectory // Toolchains + .parentDirectory // case .macOS, .linux, .android: return compilerPath - .parentDirectory // bin - .parentDirectory // usr - .parentDirectory // + .parentDirectory // bin + .parentDirectory // usr + .parentDirectory // case .freebsd, .openbsd: return compilerPath - .parentDirectory // bin - .parentDirectory // local - .parentDirectory // usr - .parentDirectory // + .parentDirectory // bin + .parentDirectory // local + .parentDirectory // usr + .parentDirectory // case .unknown: throw UnknownToolchainLayout(os: os) } @@ -140,11 +140,11 @@ extension Toolchain { public var extraCCFlags: [String] { extraFlags.cCompilerFlags } - + public var extraCPPFlags: [String] { extraFlags.cxxCompilerFlags } - + public var extraSwiftCFlags: [String] { extraFlags.swiftCompilerFlags } diff --git a/Sources/PackageModel/ToolchainConfiguration.swift b/Sources/PackageModel/ToolchainConfiguration.swift index 79d49a1aa04..df3373cb8f2 100644 --- a/Sources/PackageModel/ToolchainConfiguration.swift +++ b/Sources/PackageModel/ToolchainConfiguration.swift @@ -66,9 +66,11 @@ public struct ToolchainConfiguration { xctestPath: AbsolutePath? = nil, swiftTestingPath: AbsolutePath? = nil ) { - let swiftPMLibrariesLocation = swiftPMLibrariesLocation ?? { - return .init(swiftCompilerPath: swiftCompilerPath) - }() + let swiftPMLibrariesLocation = + swiftPMLibrariesLocation + ?? { + return .init(swiftCompilerPath: swiftCompilerPath) + }() self.librarianPath = librarianPath self.swiftCompilerPath = swiftCompilerPath @@ -97,23 +99,23 @@ extension ToolchainConfiguration { pluginLibraryMinimumDeploymentTarget: PlatformVersion? = nil ) { #if os(macOS) - if let manifestLibraryMinimumDeploymentTarget { - self.manifestLibraryMinimumDeploymentTarget = manifestLibraryMinimumDeploymentTarget - } else if let manifestLibraryMinimumDeploymentTarget = try? MinimumDeploymentTarget.default.computeMinimumDeploymentTarget(of: Self.macOSManifestLibraryPath(for: manifestLibraryPath), platform: .macOS) { - self.manifestLibraryMinimumDeploymentTarget = manifestLibraryMinimumDeploymentTarget - } else { - self.manifestLibraryMinimumDeploymentTarget = nil - } - - if let pluginLibraryMinimumDeploymentTarget { - self.pluginLibraryMinimumDeploymentTarget = pluginLibraryMinimumDeploymentTarget - } else if let pluginLibraryMinimumDeploymentTarget = try? MinimumDeploymentTarget.default.computeMinimumDeploymentTarget(of: Self.macOSPluginLibraryPath(for: pluginLibraryPath), platform: .macOS) { - self.pluginLibraryMinimumDeploymentTarget = pluginLibraryMinimumDeploymentTarget - } else { - self.pluginLibraryMinimumDeploymentTarget = nil - } + if let manifestLibraryMinimumDeploymentTarget { + self.manifestLibraryMinimumDeploymentTarget = manifestLibraryMinimumDeploymentTarget + } else if let manifestLibraryMinimumDeploymentTarget = try? MinimumDeploymentTarget.default.computeMinimumDeploymentTarget(of: Self.macOSManifestLibraryPath(for: manifestLibraryPath), platform: .macOS) { + self.manifestLibraryMinimumDeploymentTarget = manifestLibraryMinimumDeploymentTarget + } else { + self.manifestLibraryMinimumDeploymentTarget = nil + } + + if let pluginLibraryMinimumDeploymentTarget { + self.pluginLibraryMinimumDeploymentTarget = pluginLibraryMinimumDeploymentTarget + } else if let pluginLibraryMinimumDeploymentTarget = try? MinimumDeploymentTarget.default.computeMinimumDeploymentTarget(of: Self.macOSPluginLibraryPath(for: pluginLibraryPath), platform: .macOS) { + self.pluginLibraryMinimumDeploymentTarget = pluginLibraryMinimumDeploymentTarget + } else { + self.pluginLibraryMinimumDeploymentTarget = nil + } #else - precondition(manifestLibraryMinimumDeploymentTarget == nil && pluginLibraryMinimumDeploymentTarget == nil, "deployment targets can only be specified on macOS") + precondition(manifestLibraryMinimumDeploymentTarget == nil && pluginLibraryMinimumDeploymentTarget == nil, "deployment targets can only be specified on macOS") #endif self.manifestLibraryPath = manifestLibraryPath @@ -142,42 +144,44 @@ extension ToolchainConfiguration { public init(swiftCompilerPath: AbsolutePath, manifestLibraryMinimumDeploymentTarget: PlatformVersion? = nil, pluginLibraryMinimumDeploymentTarget: PlatformVersion? = nil) { let rootPath = swiftCompilerPath.parentDirectory.parentDirectory.appending(components: "lib", "swift", "pm") - self.init(root: rootPath, - manifestLibraryMinimumDeploymentTarget: manifestLibraryMinimumDeploymentTarget, - pluginLibraryMinimumDeploymentTarget: pluginLibraryMinimumDeploymentTarget) + self.init( + root: rootPath, + manifestLibraryMinimumDeploymentTarget: manifestLibraryMinimumDeploymentTarget, + pluginLibraryMinimumDeploymentTarget: pluginLibraryMinimumDeploymentTarget + ) } -#if os(macOS) - public var manifestLibraryMinimumDeploymentTarget: PlatformVersion? - public var pluginLibraryMinimumDeploymentTarget: PlatformVersion? - - private static func macOSManifestLibraryPath(for manifestAPI: AbsolutePath) -> AbsolutePath { - if manifestAPI.extension == "framework" { - return manifestAPI.appending("PackageDescription") - } else { - // note: this is not correct for all platforms, but we only actually use it on macOS. - return manifestAPI.appending("libPackageDescription.dylib") + #if os(macOS) + public var manifestLibraryMinimumDeploymentTarget: PlatformVersion? + public var pluginLibraryMinimumDeploymentTarget: PlatformVersion? + + private static func macOSManifestLibraryPath(for manifestAPI: AbsolutePath) -> AbsolutePath { + if manifestAPI.extension == "framework" { + return manifestAPI.appending("PackageDescription") + } else { + // note: this is not correct for all platforms, but we only actually use it on macOS. + return manifestAPI.appending("libPackageDescription.dylib") + } } - } - public var macOSManifestLibraryPath: AbsolutePath { - return Self.macOSManifestLibraryPath(for: manifestLibraryPath) - } + public var macOSManifestLibraryPath: AbsolutePath { + return Self.macOSManifestLibraryPath(for: manifestLibraryPath) + } - private static func macOSPluginLibraryPath(for pluginAPI: AbsolutePath) -> AbsolutePath { - // if runtimePath is set to "PackageFrameworks" that means we could be developing SwiftPM in Xcode - // which produces a framework for dynamic package products. - if pluginAPI.extension == "framework" { - return pluginAPI.appending("PackagePlugin") - } else { - // note: this is not correct for all platforms, but we only actually use it on macOS. - return pluginAPI.appending("libPackagePlugin.dylib") + private static func macOSPluginLibraryPath(for pluginAPI: AbsolutePath) -> AbsolutePath { + // if runtimePath is set to "PackageFrameworks" that means we could be developing SwiftPM in Xcode + // which produces a framework for dynamic package products. + if pluginAPI.extension == "framework" { + return pluginAPI.appending("PackagePlugin") + } else { + // note: this is not correct for all platforms, but we only actually use it on macOS. + return pluginAPI.appending("libPackagePlugin.dylib") + } } - } - public var macOSPluginLibraryPath: AbsolutePath { - return Self.macOSPluginLibraryPath(for: pluginLibraryPath) - } -#endif + public var macOSPluginLibraryPath: AbsolutePath { + return Self.macOSPluginLibraryPath(for: pluginLibraryPath) + } + #endif } } diff --git a/Sources/PackageModel/ToolsVersion.swift b/Sources/PackageModel/ToolsVersion.swift index cded5bf9467..37141bce674 100644 --- a/Sources/PackageModel/ToolsVersion.swift +++ b/Sources/PackageModel/ToolsVersion.swift @@ -37,10 +37,10 @@ public struct ToolsVersion: Equatable, Hashable, Codable, Sendable { public static let vNext = ToolsVersion(version: "999.0.0") /// The current tools version in use. - public static let current = ToolsVersion(string: - "\(SwiftVersion.current.major)." + - "\(SwiftVersion.current.minor)." + - "\(SwiftVersion.current.patch)")! + public static let current = ToolsVersion( + string: + "\(SwiftVersion.current.major)." + "\(SwiftVersion.current.minor)." + "\(SwiftVersion.current.patch)" + )! /// The minimum tools version that is required by the package manager. public static let minimumRequired: ToolsVersion = .v4 @@ -49,16 +49,16 @@ public struct ToolsVersion: Equatable, Hashable, Codable, Sendable { /// addition that specifying the patch version is optional. static let toolsVersionRegex = try! NSRegularExpression( pattern: #""" - ^ - (\d+)\.(\d+)(?:\.(\d+))? - ( - \-[A-Za-z\d]+(?:\.[A-Za-z\d]+)* - )? - ( - \+[A-Za-z\d]+(?:\.[A-Za-z\d]+)* - )? - $ - """#, + ^ + (\d+)\.(\d+)(?:\.(\d+))? + ( + \-[A-Za-z\d]+(?:\.[A-Za-z\d]+)* + )? + ( + \+[A-Za-z\d]+(?:\.[A-Za-z\d]+)* + )? + $ + """#, options: [.allowCommentsAndWhitespace] ) @@ -87,8 +87,13 @@ public struct ToolsVersion: Equatable, Hashable, Codable, Sendable { /// Create an instance of tools version from a given string. public init?(string: String) { - guard let match = ToolsVersion.toolsVersionRegex.firstMatch( - in: string, options: [], range: NSRange(location: 0, length: string.count)) else { + guard + let match = ToolsVersion.toolsVersionRegex.firstMatch( + in: string, + options: [], + range: NSRange(location: 0, length: string.count) + ) + else { return nil } // The regex succeeded, compute individual components. @@ -168,9 +173,9 @@ public struct ToolsVersion: Equatable, Hashable, Codable, Sendable { /// The subpath to the PackageDescription runtime library. public var runtimeSubpath: RelativePath { if self < .v4_2 { - return try! RelativePath(validating: "4") // try! safe + return try! RelativePath(validating: "4") // try! safe } - return try! RelativePath(validating: "4_2") // try! safe + return try! RelativePath(validating: "4_2") // try! safe } /// The swift language version based on this tools version. diff --git a/Sources/PackageModel/Toolset.swift b/Sources/PackageModel/Toolset.swift index 09ce03e4168..17c0575b75d 100644 --- a/Sources/PackageModel/Toolset.swift +++ b/Sources/PackageModel/Toolset.swift @@ -81,9 +81,10 @@ extension Toolset { ) } - let rootPaths = try decoded.rootPath.map { - [try AbsolutePath(validating: $0, relativeTo: toolsetPath.parentDirectory)] - } ?? [] + let rootPaths = + try decoded.rootPath.map { + [try AbsolutePath(validating: $0, relativeTo: toolsetPath.parentDirectory)] + } ?? [] var knownTools = [KnownTool: ToolProperties]() var hasEmptyToolConfiguration = false @@ -109,10 +110,10 @@ extension Toolset { // don't keep track of a tool with no path and CLI options specified. observabilityScope.emit( error: - """ - Tool `\(knownTool.rawValue) in toolset configuration at `\(toolsetPath)` has neither `path` nor \ - `extraCLIOptions` properties specified with valid values, skipping it. - """ + """ + Tool `\(knownTool.rawValue) in toolset configuration at `\(toolsetPath)` has neither `path` nor \ + `extraCLIOptions` properties specified with valid values, skipping it. + """ ) hasEmptyToolConfiguration = true continue diff --git a/Sources/PackageModel/UserToolchain.swift b/Sources/PackageModel/UserToolchain.swift index 69edefd7132..dc3eaa18480 100644 --- a/Sources/PackageModel/UserToolchain.swift +++ b/Sources/PackageModel/UserToolchain.swift @@ -18,9 +18,9 @@ import enum TSCBasic.JSON import class Basics.AsyncProcess #if os(Windows) -private let hostExecutableSuffix = ".exe" + private let hostExecutableSuffix = ".exe" #else -private let hostExecutableSuffix = "" + private let hostExecutableSuffix = "" #endif // FIXME: This is messy and needs a redesign. @@ -190,9 +190,9 @@ public final class UserToolchain: Toolchain { ) throws -> AbsolutePath { if useXcrun { #if os(macOS) - let foundPath = try AsyncProcess.checkNonZeroExit(arguments: ["/usr/bin/xcrun", "--find", name]) - .spm_chomp() - return try AbsolutePath(validating: foundPath) + let foundPath = try AsyncProcess.checkNonZeroExit(arguments: ["/usr/bin/xcrun", "--find", name]) + .spm_chomp() + return try AbsolutePath(validating: foundPath) #endif } @@ -444,9 +444,9 @@ public final class UserToolchain: Toolchain { // Assume the vendor is Apple on macOS. // FIXME: This might not be the best way to determine this. #if os(macOS) - return true + return true #else - return false + return false #endif } @@ -527,23 +527,24 @@ public final class UserToolchain: Toolchain { ) } -#if os(macOS) - public func getSwiftTestingHelper() throws -> AbsolutePath { - // The helper would be located in `.build/` directory when - // SwiftPM is built locally and `usr/libexec/swift/pm` directory in - // an installed version. - let binDirectories = self.swiftSDK.toolset.rootPaths + - self.swiftSDK.toolset.rootPaths.map { - $0.parentDirectory.appending(components: ["libexec", "swift", "pm"]) - } + #if os(macOS) + public func getSwiftTestingHelper() throws -> AbsolutePath { + // The helper would be located in `.build/` directory when + // SwiftPM is built locally and `usr/libexec/swift/pm` directory in + // an installed version. + let binDirectories = + self.swiftSDK.toolset.rootPaths + + self.swiftSDK.toolset.rootPaths.map { + $0.parentDirectory.appending(components: ["libexec", "swift", "pm"]) + } - return try UserToolchain.getTool( - "swiftpm-testing-helper", - binDirectories: binDirectories, - fileSystem: self.fileSystem - ) - } -#endif + return try UserToolchain.getTool( + "swiftpm-testing-helper", + binDirectories: binDirectories, + fileSystem: self.fileSystem + ) + } + #endif internal static func deriveSwiftCFlags( triple: Basics.Triple, @@ -600,8 +601,8 @@ public final class UserToolchain: Toolchain { ) { let XCTestInstallation: AbsolutePath = platform.appending("Developer") - .appending("Library") - .appending("XCTest-\(info.defaults.xctestVersion)") + .appending("Library") + .appending("XCTest-\(info.defaults.xctestVersion)") xctest = try [ "-I", @@ -649,8 +650,8 @@ public final class UserToolchain: Toolchain { if let swiftTestingVersion = info.defaults.swiftTestingVersion { let swiftTestingInstallation: AbsolutePath = platform.appending("Developer") - .appending("Library") - .appending("Testing-\(swiftTestingVersion)") + .appending("Library") + .appending("Testing-\(swiftTestingVersion)") swiftTesting = try [ "-I", @@ -662,7 +663,7 @@ public final class UserToolchain: Toolchain { AbsolutePath( validating: "usr/lib/swift/windows/\(triple.archName)", relativeTo: swiftTestingInstallation - ).pathString + ).pathString, ] } @@ -676,11 +677,10 @@ public final class UserToolchain: Toolchain { return swiftCompilerFlags } - return ( - triple.isDarwin() || triple.isAndroid() || triple.isWASI() || triple.isWindows() - ? ["-sdk", sdkDir.pathString] - : [] - ) + swiftCompilerFlags + return + (triple.isDarwin() || triple.isAndroid() || triple.isWASI() || triple.isWindows() + ? ["-sdk", sdkDir.pathString] + : []) + swiftCompilerFlags } // MARK: - initializer @@ -750,7 +750,8 @@ public final class UserToolchain: Toolchain { self.installedSwiftPMConfiguration = try Self.loadJSONResource( config: path, type: InstalledSwiftPMConfiguration.self, - default: InstalledSwiftPMConfiguration.default) + default: InstalledSwiftPMConfiguration.default + ) } var triple: Basics.Triple @@ -792,7 +793,7 @@ public final class UserToolchain: Toolchain { if swiftTestingPath.extension == "framework" { swiftCompilerFlags += ["-F", swiftTestingPath.pathString] - // Otherwise Swift Testing is assumed to be a swiftmodule + library, so use -I and -L. + // Otherwise Swift Testing is assumed to be a swiftmodule + library, so use -I and -L. } else { swiftCompilerFlags += [ "-I", swiftTestingPath.pathString, @@ -824,20 +825,23 @@ public final class UserToolchain: Toolchain { cxxCompilerFlags: swiftSDK.toolset.knownTools[.cxxCompiler]?.extraCLIOptions ?? [], swiftCompilerFlags: swiftCompilerFlags, linkerFlags: extraLinkerFlags, - xcbuildFlags: swiftSDK.toolset.knownTools[.xcbuild]?.extraCLIOptions ?? []) + xcbuildFlags: swiftSDK.toolset.knownTools[.xcbuild]?.extraCLIOptions ?? [] + ) self.includeSearchPaths = swiftSDK.pathsConfiguration.includeSearchPaths ?? [] self.librarySearchPaths = swiftSDK.pathsConfiguration.includeSearchPaths ?? [] - self.librarianPath = try swiftSDK.toolset.knownTools[.librarian]?.path ?? UserToolchain.determineLibrarian( - triple: triple, - binDirectories: swiftSDK.toolset.rootPaths, - useXcrun: useXcrun, - environment: environment, - searchPaths: envSearchPaths, - extraSwiftFlags: self.extraFlags.swiftCompilerFlags, - fileSystem: fileSystem - ) + self.librarianPath = + try swiftSDK.toolset.knownTools[.librarian]?.path + ?? UserToolchain.determineLibrarian( + triple: triple, + binDirectories: swiftSDK.toolset.rootPaths, + useXcrun: useXcrun, + environment: environment, + searchPaths: envSearchPaths, + extraSwiftFlags: self.extraFlags.swiftCompilerFlags, + fileSystem: fileSystem + ) if let sdkDir = swiftSDK.pathsConfiguration.sdkRootPath { let sysrootFlags = [triple.isDarwin() ? "-isysroot" : "--sysroot", sdkDir.pathString] @@ -882,12 +886,14 @@ public final class UserToolchain: Toolchain { } } - let swiftPMLibrariesLocation = try customLibrariesLocation ?? Self.deriveSwiftPMLibrariesLocation( - swiftCompilerPath: swiftCompilerPath, - swiftSDK: swiftSDK, - environment: environment, - fileSystem: fileSystem - ) + let swiftPMLibrariesLocation = + try customLibrariesLocation + ?? Self.deriveSwiftPMLibrariesLocation( + swiftCompilerPath: swiftCompilerPath, + swiftSDK: swiftSDK, + environment: environment, + fileSystem: fileSystem + ) let xctestPath: AbsolutePath? if case .custom(_, let useXcrun) = searchStrategy, !useXcrun { @@ -929,9 +935,9 @@ public final class UserToolchain: Toolchain { // We pick the first path which exists in an environment variable // delimited by the platform specific string separator. #if os(Windows) - let separator: Character = ";" + let separator: Character = ";" #else - let separator: Character = ":" + let separator: Character = ":" #endif let paths = pathEnvVariable.split(separator: separator).map(String.init) for pathString in paths { @@ -998,7 +1004,8 @@ public final class UserToolchain: Toolchain { if triple.isDarwin() { let pluginServerPathFindArgs = ["/usr/bin/xcrun", "--find", "swift-plugin-server"] if let path = try? AsyncProcess.checkNonZeroExit(arguments: pluginServerPathFindArgs, environment: [:]) - .spm_chomp() { + .spm_chomp() + { return try AbsolutePath(validating: path) } } @@ -1010,13 +1017,14 @@ public final class UserToolchain: Toolchain { environment: Environment, fileSystem: any FileSystem ) -> (AbsolutePath, WindowsPlatformInfo)? { - let sdkRoot: AbsolutePath? = if let sdkDir = swiftSDK.pathsConfiguration.sdkRootPath { - sdkDir - } else if let sdkDir = environment.windowsSDKRoot { - sdkDir - } else { - nil - } + let sdkRoot: AbsolutePath? = + if let sdkDir = swiftSDK.pathsConfiguration.sdkRootPath { + sdkDir + } else if let sdkDir = environment.windowsSDKRoot { + sdkDir + } else { + nil + } guard let sdkRoot else { return nil @@ -1030,11 +1038,13 @@ public final class UserToolchain: Toolchain { // SDKROOT points to [PLATFORM].sdk let platform = sdkRoot.parentDirectory.parentDirectory.parentDirectory - guard let info = WindowsPlatformInfo( - reading: platform.appending("Info.plist"), - observabilityScope: nil, - filesystem: fileSystem - ) else { + guard + let info = WindowsPlatformInfo( + reading: platform.appending("Info.plist"), + observabilityScope: nil, + filesystem: fileSystem + ) + else { return nil } @@ -1064,8 +1074,8 @@ public final class UserToolchain: Toolchain { ) { let xctest: AbsolutePath = platform.appending("Developer") - .appending("Library") - .appending("XCTest-\(info.defaults.xctestVersion)") + .appending("Library") + .appending("XCTest-\(info.defaults.xctestVersion)") // Migration Path // @@ -1076,34 +1086,34 @@ public final class UserToolchain: Toolchain { // new variant which has an architecture subdirectory in `bin` // if available. switch triple.arch { - case .x86_64: // amd64 x86_64 x86_64h + case .x86_64: // amd64 x86_64 x86_64h let path: AbsolutePath = xctest.appending("usr") - .appending("bin64") + .appending("bin64") if fileSystem.exists(path) { return path } - case .x86: // i386 i486 i586 i686 i786 i886 i986 + case .x86: // i386 i486 i586 i686 i786 i886 i986 let path: AbsolutePath = xctest.appending("usr") - .appending("bin32") + .appending("bin32") if fileSystem.exists(path) { return path } - case .arm: // armv7 and many more + case .arm: // armv7 and many more let path: AbsolutePath = xctest.appending("usr") - .appending("bin32a") + .appending("bin32a") if fileSystem.exists(path) { return path } - case .aarch64: // aarch6 arm64 + case .aarch64: // aarch6 arm64 let path: AbsolutePath = xctest.appending("usr") - .appending("bin64a") + .appending("bin64a") if fileSystem.exists(path) { return path } @@ -1149,11 +1159,13 @@ public final class UserToolchain: Toolchain { return testingLibDir } } else if triple.isWindows() { - guard let (platform, info) = getWindowsPlatformInfo( - swiftSDK: swiftSDK, - environment: environment, - fileSystem: fileSystem - ) else { + guard + let (platform, info) = getWindowsPlatformInfo( + swiftSDK: swiftSDK, + environment: environment, + fileSystem: fileSystem + ) + else { return nil } @@ -1163,25 +1175,26 @@ public final class UserToolchain: Toolchain { let swiftTesting: AbsolutePath = platform.appending("Developer") - .appending("Library") - .appending("Testing-\(swiftTestingVersion)") - - let binPath: AbsolutePath? = switch triple.arch { - case .x86_64: // amd64 x86_64 x86_64h - swiftTesting.appending("usr") - .appending("bin64") - case .x86: // i386 i486 i586 i686 i786 i886 i986 - swiftTesting.appending("usr") - .appending("bin32") - case .arm: // armv7 and many more - swiftTesting.appending("usr") - .appending("bin32a") - case .aarch64: // aarch6 arm64 - swiftTesting.appending("usr") - .appending("bin64a") - default: - nil - } + .appending("Library") + .appending("Testing-\(swiftTestingVersion)") + + let binPath: AbsolutePath? = + switch triple.arch { + case .x86_64: // amd64 x86_64 x86_64h + swiftTesting.appending("usr") + .appending("bin64") + case .x86: // i386 i486 i586 i686 i786 i886 i986 + swiftTesting.appending("usr") + .appending("bin32") + case .arm: // armv7 and many more + swiftTesting.appending("usr") + .appending("bin32a") + case .aarch64: // aarch6 arm64 + swiftTesting.appending("usr") + .appending("bin64a") + default: + nil + } if let path = binPath, fileSystem.exists(path) { return path @@ -1249,7 +1262,9 @@ public final class UserToolchain: Toolchain { } private static func loadJSONResource( - config: AbsolutePath, type: T.Type, `default`: T + config: AbsolutePath, + type: T.Type, + `default`: T ) throws -> T { @@ -1257,7 +1272,8 @@ public final class UserToolchain: Toolchain { return try JSONDecoder.makeWithDefaults().decode( path: config, fileSystem: localFileSystem, - as: type) + as: type + ) } return `default` diff --git a/Sources/PackageModel/WindowsToolchainInfo.swift b/Sources/PackageModel/WindowsToolchainInfo.swift index 0e1bcbe8435..26c2f168390 100644 --- a/Sources/PackageModel/WindowsToolchainInfo.swift +++ b/Sources/PackageModel/WindowsToolchainInfo.swift @@ -16,21 +16,21 @@ import Foundation public struct WindowsSDKSettings { public struct DefaultProperties { public enum Runtime: String, Decodable { - /// MultiThreadedDebugDLL - /// Use the debug variant of the C runtime with shared linking. - case multithreadedDebugDLL = "MDd" + /// MultiThreadedDebugDLL + /// Use the debug variant of the C runtime with shared linking. + case multithreadedDebugDLL = "MDd" - /// MultiThreadedDLL - /// Use the release variant of the C runtime with shared linking. - case multithreadedDLL = "MD" + /// MultiThreadedDLL + /// Use the release variant of the C runtime with shared linking. + case multithreadedDLL = "MD" - /// MultiThreadedDebug - /// Use the debug variant of the C runtime with static linking. - case multithreadedDebug = "MTd" + /// MultiThreadedDebug + /// Use the debug variant of the C runtime with static linking. + case multithreadedDebug = "MTd" - /// MultiThreaded - /// Use the release variant of the C runtime with static linking. - case multithreaded = "MT" + /// MultiThreaded + /// Use the release variant of the C runtime with static linking. + case multithreaded = "MT" } /// DEFAULT_USE_RUNTIME - specifies the C runtime variant to use @@ -42,13 +42,13 @@ public struct WindowsSDKSettings { extension WindowsSDKSettings.DefaultProperties: Decodable { enum CodingKeys: String, CodingKey { - case runtime = "DEFAULT_USE_RUNTIME" + case runtime = "DEFAULT_USE_RUNTIME" } } extension WindowsSDKSettings: Decodable { enum CodingKeys: String, CodingKey { - case defaults = "DefaultProperties" + case defaults = "DefaultProperties" } } @@ -92,15 +92,15 @@ public struct WindowsPlatformInfo { extension WindowsPlatformInfo.DefaultProperties: Decodable { enum CodingKeys: String, CodingKey { - case xctestVersion = "XCTEST_VERSION" - case swiftTestingVersion = "SWIFT_TESTING_VERSION" - case extraSwiftCFlags = "SWIFTC_FLAGS" + case xctestVersion = "XCTEST_VERSION" + case swiftTestingVersion = "SWIFT_TESTING_VERSION" + case extraSwiftCFlags = "SWIFTC_FLAGS" } } extension WindowsPlatformInfo: Decodable { enum CodingKeys: String, CodingKey { - case defaults = "DefaultProperties" + case defaults = "DefaultProperties" } } diff --git a/Sources/PackageRegistry/ChecksumTOFU.swift b/Sources/PackageRegistry/ChecksumTOFU.swift index c819cc54d44..3fe5e8d229a 100644 --- a/Sources/PackageRegistry/ChecksumTOFU.swift +++ b/Sources/PackageRegistry/ChecksumTOFU.swift @@ -23,13 +23,16 @@ import struct TSCUtility.Version struct PackageVersionChecksumTOFU { private let fingerprintStorage: PackageFingerprintStorage? private let fingerprintCheckingMode: FingerprintCheckingMode - private let versionMetadataProvider: (PackageIdentity.RegistryIdentity, Version) async throws -> RegistryClient - .PackageVersionMetadata + private let versionMetadataProvider: + (PackageIdentity.RegistryIdentity, Version) async throws -> + RegistryClient + .PackageVersionMetadata init( fingerprintStorage: PackageFingerprintStorage?, fingerprintCheckingMode: FingerprintCheckingMode, - versionMetadataProvider: @escaping (PackageIdentity.RegistryIdentity, Version) async throws -> RegistryClient + versionMetadataProvider: @escaping (PackageIdentity.RegistryIdentity, Version) async throws -> + RegistryClient .PackageVersionMetadata ) { self.fingerprintStorage = fingerprintStorage @@ -150,12 +153,14 @@ struct PackageVersionChecksumTOFU { ) throws { let contentType = Fingerprint.ContentType.manifest(toolsVersion) - guard let expectedChecksum = try? self.readFromStorage( - package: package, - version: version, - contentType: .manifest(toolsVersion), - observabilityScope: observabilityScope - ) else { + guard + let expectedChecksum = try? self.readFromStorage( + package: package, + version: version, + contentType: .manifest(toolsVersion), + observabilityScope: observabilityScope + ) + else { return try self.writeToStorage( registry: registry, package: package, @@ -231,7 +236,7 @@ struct PackageVersionChecksumTOFU { fingerprint: fingerprint, observabilityScope: observabilityScope ) - } catch PackageFingerprintStorageError.conflict(_, let existing){ + } catch PackageFingerprintStorageError.conflict(_, let existing) { switch self.fingerprintCheckingMode { case .strict: throw RegistryError.checksumChanged(latest: checksum, previous: existing.value) diff --git a/Sources/PackageRegistry/RegistryClient.swift b/Sources/PackageRegistry/RegistryClient.swift index 320297a0c30..764de79c8dd 100644 --- a/Sources/PackageRegistry/RegistryClient.swift +++ b/Sources/PackageRegistry/RegistryClient.swift @@ -89,7 +89,7 @@ public final class RegistryClient: AsyncCancellable { let authorizationString = "\(user):\(password)" let authorizationData = Data(authorizationString.utf8) return "Basic \(authorizationData.base64EncodedString())" - case .token: // `user` value is irrelevant in this case + case .token: // `user` value is irrelevant in this case return "Bearer \(password)" } } @@ -312,8 +312,9 @@ public final class RegistryClient: AsyncCancellable { var resourceSigning: [(resource: RegistryClient.Serialization.VersionMetadata.Resource, signingEntity: SigningEntity?)] = [] for resource in versionMetadata.resources { guard let signing = resource.signing, - let signatureData = Data(base64Encoded: signing.signatureBase64Encoded), - let signatureFormat = SignatureFormat(rawValue: signing.signatureFormat) else { + let signatureData = Data(base64Encoded: signing.signatureBase64Encoded), + let signatureFormat = SignatureFormat(rawValue: signing.signatureFormat) + else { resourceSigning.append((resource, nil)) continue } @@ -464,7 +465,7 @@ public final class RegistryClient: AsyncCancellable { version: Version, timeout: DispatchTimeInterval? = .none, observabilityScope: ObservabilityScope - ) async throws -> [String: (toolsVersion: ToolsVersion, content: String?)]{ + ) async throws -> [String: (toolsVersion: ToolsVersion, content: String?)] { let (registryIdentity, registry) = try self.unwrapRegistry(from: package) try await withAvailabilityCheck( @@ -666,7 +667,7 @@ public final class RegistryClient: AsyncCancellable { if let toolsVersion = customToolsVersion { components.queryItems = [ - URLQueryItem(name: "swift-version", value: toolsVersion.description), + URLQueryItem(name: "swift-version", value: toolsVersion.description) ] } @@ -1032,7 +1033,7 @@ public final class RegistryClient: AsyncCancellable { components.appendPathComponents("identifiers") components.queryItems = [ - URLQueryItem(name: "url", value: scmURL.absoluteString), + URLQueryItem(name: "url", value: scmURL.absoluteString) ] guard let url = components.url else { @@ -1222,13 +1223,15 @@ public final class RegistryClient: AsyncCancellable { var body = Data() // archive field - body.append(contentsOf: """ - --\(boundary)\r - Content-Disposition: form-data; name=\"source-archive\"\r - Content-Type: application/zip\r - Content-Transfer-Encoding: binary\r - \r\n - """.utf8) + body.append( + contentsOf: """ + --\(boundary)\r + Content-Disposition: form-data; name=\"source-archive\"\r + Content-Type: application/zip\r + Content-Transfer-Encoding: binary\r + \r\n + """.utf8 + ) body.append(packageArchiveContent) if let signature { @@ -1236,28 +1239,32 @@ public final class RegistryClient: AsyncCancellable { throw RegistryError.missingSignatureFormat } - body.append(contentsOf: """ - \r - --\(boundary)\r - Content-Disposition: form-data; name=\"source-archive-signature\"\r - Content-Type: application/octet-stream\r - Content-Transfer-Encoding: binary\r - \r\n - """.utf8) + body.append( + contentsOf: """ + \r + --\(boundary)\r + Content-Disposition: form-data; name=\"source-archive-signature\"\r + Content-Type: application/octet-stream\r + Content-Transfer-Encoding: binary\r + \r\n + """.utf8 + ) body.append(contentsOf: signature) } // metadata field if let metadataContent { - body.append(contentsOf: """ - \r - --\(boundary)\r - Content-Disposition: form-data; name=\"metadata\"\r - Content-Type: application/json\r - Content-Transfer-Encoding: quoted-printable\r - \r - \(metadataContent) - """.utf8) + body.append( + contentsOf: """ + \r + --\(boundary)\r + Content-Disposition: form-data; name=\"metadata\"\r + Content-Type: application/json\r + Content-Transfer-Encoding: quoted-printable\r + \r + \(metadataContent) + """.utf8 + ) if signature != nil { guard metadataSignature != nil else { @@ -1273,14 +1280,16 @@ public final class RegistryClient: AsyncCancellable { throw RegistryError.missingSignatureFormat } - body.append(contentsOf: """ - \r - --\(boundary)\r - Content-Disposition: form-data; name=\"metadata-signature\"\r - Content-Type: application/octet-stream\r - Content-Transfer-Encoding: binary\r - \r\n - """.utf8) + body.append( + contentsOf: """ + \r + --\(boundary)\r + Content-Disposition: form-data; name=\"metadata-signature\"\r + Content-Type: application/octet-stream\r + Content-Transfer-Encoding: binary\r + \r\n + """.utf8 + ) body.append(contentsOf: metadataSignature) } } @@ -2014,13 +2023,13 @@ extension HTTPClientHeaders { } guard let link = fields.first(where: { $0.hasPrefix("<") }).map({ String($0.dropFirst().dropLast()) }), - let url = URL(string: link) + let url = URL(string: link) else { return nil } guard let rel = fields.first(where: { $0.hasPrefix("rel=") }).flatMap({ parseLinkFieldValue($0) }), - rel == "alternate" + rel == "alternate" else { return nil } @@ -2030,8 +2039,9 @@ extension HTTPClientHeaders { return nil } - guard let toolsVersion = fields.first(where: { $0.hasPrefix("swift-tools-version=") }) - .flatMap({ parseLinkFieldValue($0) }) + guard + let toolsVersion = fields.first(where: { $0.hasPrefix("swift-tools-version=") }) + .flatMap({ parseLinkFieldValue($0) }) else { return nil } diff --git a/Sources/PackageRegistry/RegistryConfiguration.swift b/Sources/PackageRegistry/RegistryConfiguration.swift index 8b6a15d5647..f416131dd94 100644 --- a/Sources/PackageRegistry/RegistryConfiguration.swift +++ b/Sources/PackageRegistry/RegistryConfiguration.swift @@ -364,10 +364,11 @@ extension RegistryConfiguration: Codable { } self.scopedRegistries = scopedRegistries - self.registryAuthentication = try container.decodeIfPresent( - [String: Authentication].self, - forKey: .authentication - ) ?? [:] + self.registryAuthentication = + try container.decodeIfPresent( + [String: Authentication].self, + forKey: .authentication + ) ?? [:] self.security = try container.decodeIfPresent(Security.self, forKey: .security) ?? nil case nil: throw DecodingError.dataCorruptedError( @@ -430,15 +431,17 @@ extension RegistryConfiguration.Security: Codable { let container = try decoder.container(keyedBy: CodingKeys.self) self.default = try container.decodeIfPresent(Global.self, forKey: .default) ?? Global() - self.registryOverrides = try container.decodeIfPresent( - [String: RegistryOverride].self, - forKey: .registryOverrides - ) ?? [:] + self.registryOverrides = + try container.decodeIfPresent( + [String: RegistryOverride].self, + forKey: .registryOverrides + ) ?? [:] - let scopeOverridesContainer = try container.decodeIfPresent( - [String: ScopePackageOverride].self, - forKey: .scopeOverrides - ) ?? [:] + let scopeOverridesContainer = + try container.decodeIfPresent( + [String: ScopePackageOverride].self, + forKey: .scopeOverrides + ) ?? [:] var scopeOverrides: [PackageIdentity.Scope: ScopePackageOverride] = [:] for (key, scopeOverride) in scopeOverridesContainer { let scope = try PackageIdentity.Scope(validating: key) @@ -446,10 +449,11 @@ extension RegistryConfiguration.Security: Codable { } self.scopeOverrides = scopeOverrides - let packageOverridesContainer = try container.decodeIfPresent( - [String: ScopePackageOverride].self, - forKey: .packageOverrides - ) ?? [:] + let packageOverridesContainer = + try container.decodeIfPresent( + [String: ScopePackageOverride].self, + forKey: .packageOverrides + ) ?? [:] var packageOverrides: [PackageIdentity.RegistryIdentity: ScopePackageOverride] = [:] for (key, packageOverride) in packageOverridesContainer { guard let packageIdentity = PackageIdentity.plain(key).registry else { diff --git a/Sources/PackageRegistry/SignatureValidation.swift b/Sources/PackageRegistry/SignatureValidation.swift index bf5169ff138..31cf854b65f 100644 --- a/Sources/PackageRegistry/SignatureValidation.swift +++ b/Sources/PackageRegistry/SignatureValidation.swift @@ -32,8 +32,10 @@ struct SignatureValidation { private let skipSignatureValidation: Bool private let signingEntityTOFU: PackageSigningEntityTOFU - private let versionMetadataProvider: (PackageIdentity.RegistryIdentity, Version) async throws -> RegistryClient - .PackageVersionMetadata + private let versionMetadataProvider: + (PackageIdentity.RegistryIdentity, Version) async throws -> + RegistryClient + .PackageVersionMetadata private let delegate: Delegate private enum ValidationError: Error { @@ -44,7 +46,8 @@ struct SignatureValidation { skipSignatureValidation: Bool, signingEntityStorage: PackageSigningEntityStorage?, signingEntityCheckingMode: SigningEntityCheckingMode, - versionMetadataProvider: @escaping (PackageIdentity.RegistryIdentity, Version) async throws -> RegistryClient + versionMetadataProvider: @escaping (PackageIdentity.RegistryIdentity, Version) async throws -> + RegistryClient .PackageVersionMetadata, delegate: Delegate ) { @@ -350,7 +353,6 @@ struct SignatureValidation { return signingEntity; } - @available(*, noasync, message: "Use the async alternative") func validate( registry: Registry, @@ -413,12 +415,14 @@ struct SignatureValidation { // source archive is signed, so the manifest must also be signed guard let manifestSignature = try ManifestSignatureParser.parse(utf8String: manifestContent) else { - throw ValidationError.passthrough(RegistryError.manifestNotSigned( - registry: registry, - package: package.underlying, - version: version, - toolsVersion: toolsVersion - )) + throw ValidationError.passthrough( + RegistryError.manifestNotSigned( + registry: registry, + package: package.underlying, + version: version, + toolsVersion: toolsVersion + ) + ) } guard let signatureFormat = SignatureFormat(rawValue: manifestSignature.signatureFormat) else { diff --git a/Sources/PackageRegistry/SigningEntityTOFU.swift b/Sources/PackageRegistry/SigningEntityTOFU.swift index 5ce3299d91c..da3a7c4b368 100644 --- a/Sources/PackageRegistry/SigningEntityTOFU.swift +++ b/Sources/PackageRegistry/SigningEntityTOFU.swift @@ -117,7 +117,7 @@ struct PackageSigningEntityTOFU { // We recorded the version's signer(s) previously if !signingEntitiesForVersion.isEmpty { guard let signingEntityToCheck = signingEntity, - signingEntitiesForVersion.contains(signingEntityToCheck) + signingEntitiesForVersion.contains(signingEntityToCheck) else { // The given signer is nil or different // TODO: This could indicate a legitimate change @@ -129,7 +129,7 @@ struct PackageSigningEntityTOFU { package: package, version: version, latest: signingEntity, - existing: signingEntitiesForVersion.first!, // !-safe since signingEntitiesForVersion is non-empty + existing: signingEntitiesForVersion.first!, // !-safe since signingEntitiesForVersion is non-empty observabilityScope: observabilityScope ) return false @@ -144,7 +144,7 @@ struct PackageSigningEntityTOFU { case .some(let signingEntity): // Does the package have an expected signer? if let expectedSigner = packageSigners.expectedSigner, - version >= expectedSigner.fromVersion + version >= expectedSigner.fromVersion { // Signer is as expected if signingEntity == expectedSigner.signingEntity { @@ -159,8 +159,8 @@ struct PackageSigningEntityTOFU { // set to v1.5, then it should not be a TOFU failure if we see signer A // for v1.9. if let knownSigner = packageSigners.signers[signingEntity], - let highestKnownVersion = knownSigner.versions.sorted(by: >).first, - version < highestKnownVersion + let highestKnownVersion = knownSigner.versions.sorted(by: >).first, + version < highestKnownVersion { return true } diff --git a/Sources/PackageRegistryCommand/PackageRegistryCommand+Auth.swift b/Sources/PackageRegistryCommand/PackageRegistryCommand+Auth.swift index 2c01cf1413d..0713e1659c1 100644 --- a/Sources/PackageRegistryCommand/PackageRegistryCommand+Auth.swift +++ b/Sources/PackageRegistryCommand/PackageRegistryCommand+Auth.swift @@ -24,78 +24,78 @@ import Workspace import struct TSCBasic.SHA256 #if os(Windows) -import WinSDK + import WinSDK -private func readpassword(_ prompt: String) throws -> String { - enum StaticStorage { - static var buffer: UnsafeMutableBufferPointer = - .allocate(capacity: PackageRegistryCommand.Login.passwordBufferSize) - } - - let hStdIn: HANDLE = GetStdHandle(STD_INPUT_HANDLE) - if hStdIn == INVALID_HANDLE_VALUE { - throw StringError("unable to read input: GetStdHandle returns INVALID_HANDLE_VALUE") - } - - var dwMode: DWORD = 0 - guard GetConsoleMode(hStdIn, &dwMode) else { - throw StringError("unable to read input: GetConsoleMode failed") - } + private func readpassword(_ prompt: String) throws -> String { + enum StaticStorage { + static var buffer: UnsafeMutableBufferPointer = + .allocate(capacity: PackageRegistryCommand.Login.passwordBufferSize) + } - print(prompt, terminator: "") + let hStdIn: HANDLE = GetStdHandle(STD_INPUT_HANDLE) + if hStdIn == INVALID_HANDLE_VALUE { + throw StringError("unable to read input: GetStdHandle returns INVALID_HANDLE_VALUE") + } - guard SetConsoleMode(hStdIn, DWORD(ENABLE_LINE_INPUT)) else { - throw StringError("unable to read input: SetConsoleMode failed") - } - defer { SetConsoleMode(hStdIn, dwMode) } - - var dwNumberOfCharsRead: DWORD = 0 - _ = ReadConsoleA( - hStdIn, - StaticStorage.buffer.baseAddress, - DWORD(StaticStorage.buffer.count), - &dwNumberOfCharsRead, - nil - ) - - let password = String(cString: UnsafePointer(StaticStorage.buffer.baseAddress!)) - guard password.count <= PackageRegistryCommand.Login.maxPasswordLength else { - throw PackageRegistryCommand.ValidationError - .credentialLengthLimitExceeded(PackageRegistryCommand.Login.maxPasswordLength) - } - return password -} -#else -#if canImport(Android) -import Android -#endif + var dwMode: DWORD = 0 + guard GetConsoleMode(hStdIn, &dwMode) else { + throw StringError("unable to read input: GetConsoleMode failed") + } -private func readpassword(_ prompt: String) throws -> String { - let password: String + print(prompt, terminator: "") - #if canImport(Darwin) - var buffer = [CChar](repeating: 0, count: PackageRegistryCommand.Login.passwordBufferSize) - password = try withExtendedLifetime(buffer) { - guard let passwordPtr = readpassphrase(prompt, &buffer, buffer.count, 0) else { - throw StringError("unable to read input") + guard SetConsoleMode(hStdIn, DWORD(ENABLE_LINE_INPUT)) else { + throw StringError("unable to read input: SetConsoleMode failed") } + defer { SetConsoleMode(hStdIn, dwMode) } + + var dwNumberOfCharsRead: DWORD = 0 + _ = ReadConsoleA( + hStdIn, + StaticStorage.buffer.baseAddress, + DWORD(StaticStorage.buffer.count), + &dwNumberOfCharsRead, + nil + ) - return String(cString: passwordPtr) + let password = String(cString: UnsafePointer(StaticStorage.buffer.baseAddress!)) + guard password.count <= PackageRegistryCommand.Login.maxPasswordLength else { + throw PackageRegistryCommand.ValidationError + .credentialLengthLimitExceeded(PackageRegistryCommand.Login.maxPasswordLength) + } + return password } - #elseif canImport(Android) - throw StringError("unable to read input - not implemented on this platform") - #else - // GNU C implementation of getpass has no limit on the password length - // (https://man7.org/linux/man-pages/man3/getpass.3.html) - password = String(cString: getpass(prompt)) +#else + #if canImport(Android) + import Android #endif - guard password.count <= PackageRegistryCommand.Login.maxPasswordLength else { - throw PackageRegistryCommand.ValidationError - .credentialLengthLimitExceeded(PackageRegistryCommand.Login.maxPasswordLength) + private func readpassword(_ prompt: String) throws -> String { + let password: String + + #if canImport(Darwin) + var buffer = [CChar](repeating: 0, count: PackageRegistryCommand.Login.passwordBufferSize) + password = try withExtendedLifetime(buffer) { + guard let passwordPtr = readpassphrase(prompt, &buffer, buffer.count, 0) else { + throw StringError("unable to read input") + } + + return String(cString: passwordPtr) + } + #elseif canImport(Android) + throw StringError("unable to read input - not implemented on this platform") + #else + // GNU C implementation of getpass has no limit on the password length + // (https://man7.org/linux/man-pages/man3/getpass.3.html) + password = String(cString: getpass(prompt)) + #endif + + guard password.count <= PackageRegistryCommand.Login.maxPasswordLength else { + throw PackageRegistryCommand.ValidationError + .credentialLengthLimitExceeded(PackageRegistryCommand.Login.maxPasswordLength) + } + return password } - return password -} #endif extension PackageRegistryCommand { @@ -191,7 +191,7 @@ extension PackageRegistryCommand { // User provided password storePassword = password } else if let stored = authorizationProvider.authentication(for: registryURL), - stored.user == storeUsername + stored.user == storeUsername { // Password found in credential store storePassword = stored.password @@ -213,7 +213,7 @@ extension PackageRegistryCommand { storePassword = try localFileSystem.readFileContents(tokenFilePath) .trimmingCharacters(in: .whitespacesAndNewlines) } else if let stored = authorizationProvider.authentication(for: registryURL), - stored.user == storeUsername + stored.user == storeUsername { // Token found in credential store storePassword = stored.password @@ -246,7 +246,6 @@ extension PackageRegistryCommand { let loginURL = try Self.loginURL(from: registryURL, loginAPIPath: loginAPIPath) - // Build a RegistryConfiguration with the given authentication settings var registryConfiguration = configuration.configuration try registryConfiguration.add(authentication: .init(type: authenticationType, loginAPIPath: loginAPIPath), for: registryURL) @@ -280,17 +279,21 @@ extension PackageRegistryCommand { // Prompt if writing to netrc file and --no-confirm is not set if saveChanges, !osStore, !self.noConfirm { if self.globalOptions.security.forceNetrc { - print(""" + print( + """ - WARNING: You choose to use netrc file instead of the operating system's secure credential store. - Your credentials will be written out to netrc file. - """) + WARNING: You choose to use netrc file instead of the operating system's secure credential store. + Your credentials will be written out to netrc file. + """ + ) } else { - print(""" + print( + """ - WARNING: Secure credential store is not supported on this platform. - Your credentials will be written out to netrc file. - """) + WARNING: Secure credential store is not supported on this platform. + Your credentials will be written out to netrc file. + """ + ) } print("Continue? (Yes/No): ") guard readLine(strippingNewline: true)?.lowercased() == "yes" else { diff --git a/Sources/PackageRegistryCommand/PackageRegistryCommand+Publish.swift b/Sources/PackageRegistryCommand/PackageRegistryCommand+Publish.swift index abac4d8628a..85ef33de545 100644 --- a/Sources/PackageRegistryCommand/PackageRegistryCommand+Publish.swift +++ b/Sources/PackageRegistryCommand/PackageRegistryCommand+Publish.swift @@ -22,9 +22,9 @@ import PackageSigning import Workspace #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import X509 // FIXME: need this import or else SwiftSigningIdentity initializer fails + @_implementationOnly import X509 // FIXME: need this import or else SwiftSigningIdentity initializer fails #else -import X509 + import X509 #endif import struct TSCBasic.ByteString @@ -65,7 +65,7 @@ extension PackageRegistryCommand { ) var customMetadataPath: AbsolutePath? - @Option(help: .hidden) // help: "Signature format identifier. Defaults to 'cms-1.0.0'. + @Option(help: .hidden) // help: "Signature format identifier. Defaults to 'cms-1.0.0'. var signatureFormat: SignatureFormat = .cms_1_0_0 @Option( @@ -120,7 +120,9 @@ extension PackageRegistryCommand { } } - let workingDirectory = self.customWorkingDirectory ?? Workspace.DefaultLocations + let workingDirectory = + self.customWorkingDirectory + ?? Workspace.DefaultLocations .scratchDirectory(forRootPackage: packageDirectory).appending(components: ["registry", "publish"]) if localFileSystem.exists(workingDirectory) { try localFileSystem.removeFileTree(workingDirectory) @@ -157,8 +159,10 @@ extension PackageRegistryCommand { ) // step 1: publishing configuration - let signingRequired = self.signingIdentity != nil || self.privateKeyPath != nil || !self - .certificateChainPaths.isEmpty + let signingRequired = + self.signingIdentity != nil || self.privateKeyPath != nil + || !self + .certificateChainPaths.isEmpty let archivePath: AbsolutePath var archiveSignature: [UInt8]? = .none diff --git a/Sources/PackageSigning/CertificateStores.swift b/Sources/PackageSigning/CertificateStores.swift index 7d001f8484f..109a45dfedc 100644 --- a/Sources/PackageSigning/CertificateStores.swift +++ b/Sources/PackageSigning/CertificateStores.swift @@ -11,11 +11,11 @@ //===----------------------------------------------------------------------===// #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import X509 -@_implementationOnly import SwiftASN1 + @_implementationOnly import X509 + @_implementationOnly import SwiftASN1 #else -import X509 -import SwiftASN1 + import X509 + import SwiftASN1 #endif enum Certificates { diff --git a/Sources/PackageSigning/SignatureProvider.swift b/Sources/PackageSigning/SignatureProvider.swift index 24ac4a986ab..9cb353ed79d 100644 --- a/Sources/PackageSigning/SignatureProvider.swift +++ b/Sources/PackageSigning/SignatureProvider.swift @@ -14,19 +14,19 @@ import struct Foundation.Data import struct Foundation.Date #if USE_IMPL_ONLY_IMPORTS -#if canImport(Security) -@_implementationOnly import Security -#endif + #if canImport(Security) + @_implementationOnly import Security + #endif -@_implementationOnly import SwiftASN1 -@_implementationOnly @_spi(CMS) import X509 + @_implementationOnly import SwiftASN1 + @_implementationOnly @_spi(CMS) import X509 #else -#if canImport(Security) -import Security -#endif + #if canImport(Security) + import Security + #endif -import SwiftASN1 -@_spi(CMS) import X509 + import SwiftASN1 + @_spi(CMS) import X509 #endif import Basics @@ -217,30 +217,30 @@ struct CMSSignatureProvider: SignatureProviderProtocol { observabilityScope: ObservabilityScope ) throws -> [UInt8] { #if canImport(Security) - if CFGetTypeID(identity as CFTypeRef) == SecIdentityGetTypeID() { - let secIdentity = identity as! SecIdentity // !-safe because we ensure type above + if CFGetTypeID(identity as CFTypeRef) == SecIdentityGetTypeID() { + let secIdentity = identity as! SecIdentity // !-safe because we ensure type above - var privateKey: SecKey? - let keyStatus = SecIdentityCopyPrivateKey(secIdentity, &privateKey) - guard keyStatus == errSecSuccess, let privateKey else { - throw SigningError.signingFailed("unable to get private key from SecIdentity: status \(keyStatus)") - } + var privateKey: SecKey? + let keyStatus = SecIdentityCopyPrivateKey(secIdentity, &privateKey) + guard keyStatus == errSecSuccess, let privateKey else { + throw SigningError.signingFailed("unable to get private key from SecIdentity: status \(keyStatus)") + } - let signature = try privateKey.sign(content: content, algorithm: self.signatureAlgorithm) + let signature = try privateKey.sign(content: content, algorithm: self.signatureAlgorithm) - do { - let intermediateCertificates = try intermediateCertificates.map { try Certificate($0) } + do { + let intermediateCertificates = try intermediateCertificates.map { try Certificate($0) } - return try CMS.sign( - signatureBytes: ASN1OctetString(contentBytes: ArraySlice(signature)), - signatureAlgorithm: self.signatureAlgorithm.certificateSignatureAlgorithm, - additionalIntermediateCertificates: intermediateCertificates, - certificate: try Certificate(secIdentity: secIdentity) - ) - } catch { - throw SigningError.signingFailed("\(error.interpolationDescription)") + return try CMS.sign( + signatureBytes: ASN1OctetString(contentBytes: ArraySlice(signature)), + signatureAlgorithm: self.signatureAlgorithm.certificateSignatureAlgorithm, + additionalIntermediateCertificates: intermediateCertificates, + certificate: try Certificate(secIdentity: secIdentity) + ) + } catch { + throw SigningError.signingFailed("\(error.interpolationDescription)") + } } - } #endif guard let swiftSigningIdentity = identity as? SwiftSigningIdentity else { @@ -294,7 +294,6 @@ struct CMSSignatureProvider: SignatureProviderProtocol { ) { self.buildPolicySet(configuration: verifierConfiguration, httpClient: self.httpClient) } - switch result { case .success(let valid): @@ -369,7 +368,8 @@ struct CMSSignatureProvider: SignatureProviderProtocol { let signingEntity = SigningEntity.from(certificate: signingCertificate) throw SigningError.certificateNotTrusted(signingEntity) } else { - throw SigningError + throw + SigningError .certificateInvalid("failures: \(validationFailures.map(\.policyFailureReason))") } } @@ -383,33 +383,35 @@ struct CMSSignatureProvider: SignatureProviderProtocol { } #if canImport(Security) -extension SecKey { - func sign(content: [UInt8], algorithm: SignatureAlgorithm) throws -> [UInt8] { - let secKeyAlgorithm: SecKeyAlgorithm - switch algorithm { - case .ecdsaP256: - secKeyAlgorithm = .ecdsaSignatureMessageX962SHA256 - case .rsa: - secKeyAlgorithm = .rsaSignatureMessagePKCS1v15SHA256 - } + extension SecKey { + func sign(content: [UInt8], algorithm: SignatureAlgorithm) throws -> [UInt8] { + let secKeyAlgorithm: SecKeyAlgorithm + switch algorithm { + case .ecdsaP256: + secKeyAlgorithm = .ecdsaSignatureMessageX962SHA256 + case .rsa: + secKeyAlgorithm = .rsaSignatureMessagePKCS1v15SHA256 + } - guard SecKeyIsAlgorithmSupported(self, .sign, secKeyAlgorithm) else { - throw SigningError.keyDoesNotSupportSignatureAlgorithm - } + guard SecKeyIsAlgorithmSupported(self, .sign, secKeyAlgorithm) else { + throw SigningError.keyDoesNotSupportSignatureAlgorithm + } - var error: Unmanaged? - guard let signatureData = SecKeyCreateSignature( - self, - secKeyAlgorithm, - Data(content) as CFData, - &error - ) as Data? else { - if let error = error?.takeRetainedValue() as Error? { - throw SigningError.signingFailed("\(error.interpolationDescription)") + var error: Unmanaged? + guard + let signatureData = SecKeyCreateSignature( + self, + secKeyAlgorithm, + Data(content) as CFData, + &error + ) as Data? + else { + if let error = error?.takeRetainedValue() as Error? { + throw SigningError.signingFailed("\(error.interpolationDescription)") + } + throw SigningError.signingFailed("Failed to sign with SecKey") } - throw SigningError.signingFailed("Failed to sign with SecKey") + return Array(signatureData) } - return Array(signatureData) } -} #endif diff --git a/Sources/PackageSigning/SigningEntity/FilePackageSigningEntityStorage.swift b/Sources/PackageSigning/SigningEntity/FilePackageSigningEntityStorage.swift index 28fa216ecbc..a8ab7fc7e25 100644 --- a/Sources/PackageSigning/SigningEntity/FilePackageSigningEntityStorage.swift +++ b/Sources/PackageSigning/SigningEntity/FilePackageSigningEntityStorage.swift @@ -59,7 +59,7 @@ public struct FilePackageSigningEntityStorage: PackageSigningEntityStorage { package: package, version: version, given: signingEntity, - existing: otherSigningEntities.first! // !-safe because otherSigningEntities is not empty + existing: otherSigningEntities.first! // !-safe because otherSigningEntities is not empty ) } @@ -214,9 +214,11 @@ private enum StorageModel { } func packageSigners() throws -> PackageSigners { - let signers = try Dictionary(throwingUniqueKeysWithValues: self.signers.map { - ($0.signingEntity, $0) - }) + let signers = try Dictionary( + throwingUniqueKeysWithValues: self.signers.map { + ($0.signingEntity, $0) + } + ) return PackageSigners( expectedSigner: self.expectedSigner.map { ($0.signingEntity, $0.fromVersion) }, signers: signers diff --git a/Sources/PackageSigning/SigningEntity/SigningEntity.swift b/Sources/PackageSigning/SigningEntity/SigningEntity.swift index 3fb9a444c03..fe01e8af810 100644 --- a/Sources/PackageSigning/SigningEntity/SigningEntity.swift +++ b/Sources/PackageSigning/SigningEntity/SigningEntity.swift @@ -11,11 +11,11 @@ //===----------------------------------------------------------------------===// #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import SwiftASN1 -@_implementationOnly import X509 + @_implementationOnly import SwiftASN1 + @_implementationOnly import X509 #else -import SwiftASN1 -import X509 + import SwiftASN1 + import X509 #endif // MARK: - SigningEntity is the entity that generated the signature @@ -30,9 +30,10 @@ public enum SigningEntity: Hashable, Codable, CustomStringConvertible, Sendable let organization = certificate.subject.organizationName if let type = certificate.signingEntityType, - let name = name, - let organizationalUnit = organizationalUnit, - let organization = organization { + let name = name, + let organizationalUnit = organizationalUnit, + let organization = organization + { return .recognized( type: type, name: name, @@ -82,7 +83,7 @@ public enum SigningEntity: Hashable, Codable, CustomStringConvertible, Sendable // MARK: - SigningEntity types that SwiftPM recognizes public enum SigningEntityType: String, Hashable, Codable, Sendable { - case adp // Apple Developer Program + case adp // Apple Developer Program } extension ASN1ObjectIdentifier.NameAttributes { @@ -92,9 +93,8 @@ extension ASN1ObjectIdentifier.NameAttributes { extension Certificate { var signingEntityType: SigningEntityType? { if self.hasExtension(oid: ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageMarker), - Certificates.wwdrIntermediates - .first(where: { $0.subject == self.issuer && $0.publicKey.isValidSignature(self.signature, for: self) }) != - nil + Certificates.wwdrIntermediates + .first(where: { $0.subject == self.issuer && $0.publicKey.isValidSignature(self.signature, for: self) }) != nil { return .adp } diff --git a/Sources/PackageSigning/SigningIdentity.swift b/Sources/PackageSigning/SigningIdentity.swift index ded10b2a483..71909bcad53 100644 --- a/Sources/PackageSigning/SigningIdentity.swift +++ b/Sources/PackageSigning/SigningIdentity.swift @@ -11,19 +11,19 @@ //===----------------------------------------------------------------------===// #if USE_IMPL_ONLY_IMPORTS -#if canImport(Security) -@_implementationOnly import Security -#endif + #if canImport(Security) + @_implementationOnly import Security + #endif -@_implementationOnly import Crypto -@_implementationOnly import X509 + @_implementationOnly import Crypto + @_implementationOnly import X509 #else -#if canImport(Security) -import Security -#endif + #if canImport(Security) + import Security + #endif -import Crypto -import X509 + import Crypto + import X509 #endif import Basics @@ -34,7 +34,7 @@ public protocol SigningIdentity {} // MARK: - SecIdentity conformance to SigningIdentity #if canImport(Security) -extension SecIdentity: SigningIdentity {} + extension SecIdentity: SigningIdentity {} #endif // MARK: - SwiftSigningIdentity is created using raw private key and certificate bytes @@ -84,41 +84,41 @@ public struct SigningIdentityStore { public func find(by label: String) -> [SigningIdentity] { #if os(macOS) - // Find in Keychain - let query: [String: Any] = [ - // Use kSecClassCertificate instead of kSecClassIdentity because the latter - // seems to always return all results, whether matching given label or not. - kSecClass as String: kSecClassCertificate, - kSecReturnRef as String: true, - kSecAttrLabel as String: label, - // TODO: too restrictive to require kSecAttrCanSign == true? -// kSecAttrCanSign as String: true, - kSecMatchLimit as String: kSecMatchLimitAll, - ] - - var result: CFTypeRef? - let status = SecItemCopyMatching(query as CFDictionary, &result) - guard status == errSecSuccess else { - self.observabilityScope.emit(warning: "Failed to search for '\(label)' in Keychain: status \(status)") - return [] - } + // Find in Keychain + let query: [String: Any] = [ + // Use kSecClassCertificate instead of kSecClassIdentity because the latter + // seems to always return all results, whether matching given label or not. + kSecClass as String: kSecClassCertificate, + kSecReturnRef as String: true, + kSecAttrLabel as String: label, + // TODO: too restrictive to require kSecAttrCanSign == true? + // kSecAttrCanSign as String: true, + kSecMatchLimit as String: kSecMatchLimitAll, + ] + + var result: CFTypeRef? + let status = SecItemCopyMatching(query as CFDictionary, &result) + guard status == errSecSuccess else { + self.observabilityScope.emit(warning: "Failed to search for '\(label)' in Keychain: status \(status)") + return [] + } - let certificates = result as? [SecCertificate] ?? [] - return certificates.compactMap { secCertificate in - var identity: SecIdentity? - let status = SecIdentityCreateWithCertificate(nil, secCertificate, &identity) - guard status == errSecSuccess, let identity else { - self.observabilityScope - .emit( - warning: "Failed to create SecIdentity from SecCertificate[\(secCertificate)]: status \(status)" - ) - return nil + let certificates = result as? [SecCertificate] ?? [] + return certificates.compactMap { secCertificate in + var identity: SecIdentity? + let status = SecIdentityCreateWithCertificate(nil, secCertificate, &identity) + guard status == errSecSuccess, let identity else { + self.observabilityScope + .emit( + warning: "Failed to create SecIdentity from SecCertificate[\(secCertificate)]: status \(status)" + ) + return nil + } + return identity } - return identity - } #else - // No identity store support on other platforms - return [] + // No identity store support on other platforms + return [] #endif } } diff --git a/Sources/PackageSigning/VerifierPolicies.swift b/Sources/PackageSigning/VerifierPolicies.swift index dc82439c876..5932f62b0af 100644 --- a/Sources/PackageSigning/VerifierPolicies.swift +++ b/Sources/PackageSigning/VerifierPolicies.swift @@ -18,11 +18,11 @@ import struct Foundation.URL import Basics #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import SwiftASN1 -@_implementationOnly @_spi(DisableValidityCheck) import X509 + @_implementationOnly import SwiftASN1 + @_implementationOnly @_spi(DisableValidityCheck) import X509 #else -import SwiftASN1 -@_spi(DisableValidityCheck) import X509 + import SwiftASN1 + @_spi(DisableValidityCheck) import X509 #endif extension SignatureProviderProtocol { @@ -80,10 +80,7 @@ struct _CodeSigningPolicy: VerifierPolicy { ] func chainMeetsPolicyRequirements(chain: UnverifiedCertificateChain) async -> PolicyEvaluationResult { - let isCodeSigning = ( - try? chain.leaf.extensions.extendedKeyUsage?.contains(ExtendedKeyUsage.Usage.codeSigning) - ) ?? - false + let isCodeSigning = (try? chain.leaf.extensions.extendedKeyUsage?.contains(ExtendedKeyUsage.Usage.codeSigning)) ?? false guard isCodeSigning else { return .failsToMeetPolicy(reason: "Certificate \(chain.leaf) does not have code signing extended key usage") } @@ -95,13 +92,14 @@ struct _CodeSigningPolicy: VerifierPolicy { struct _ADPCertificatePolicy: VerifierPolicy { /// Include custom marker extensions (which can be critical) so they would not /// be considered unhandled and cause certificate chain validation to fail. - let verifyingCriticalExtensions: [ASN1ObjectIdentifier] = Self.swiftPackageMarkers + let verifyingCriticalExtensions: [ASN1ObjectIdentifier] = + Self.swiftPackageMarkers + Self.developmentMarkers // Marker extensions for Swift Package certificate private static let swiftPackageMarkers: [ASN1ObjectIdentifier] = [ // This is not a critical extension but including it just in case - ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageMarker, + ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageMarker ] // Marker extensions for Development certificate (included for testing) diff --git a/Sources/PackageSigning/X509Extensions.swift b/Sources/PackageSigning/X509Extensions.swift index c6f40cbb957..a76598e6d63 100644 --- a/Sources/PackageSigning/X509Extensions.swift +++ b/Sources/PackageSigning/X509Extensions.swift @@ -13,40 +13,40 @@ import struct Foundation.Data #if USE_IMPL_ONLY_IMPORTS -#if canImport(Security) -@_implementationOnly import Security -#endif + #if canImport(Security) + @_implementationOnly import Security + #endif -@_implementationOnly import SwiftASN1 -@_implementationOnly import X509 + @_implementationOnly import SwiftASN1 + @_implementationOnly import X509 #else -#if canImport(Security) -import Security -#endif + #if canImport(Security) + import Security + #endif -import SwiftASN1 -import X509 + import SwiftASN1 + import X509 #endif import Basics import TSCBasic #if canImport(Security) -extension Certificate { - init(secCertificate: SecCertificate) throws { - let data = SecCertificateCopyData(secCertificate) as Data - self = try Certificate(Array(data)) - } + extension Certificate { + init(secCertificate: SecCertificate) throws { + let data = SecCertificateCopyData(secCertificate) as Data + self = try Certificate(Array(data)) + } - init(secIdentity: SecIdentity) throws { - var secCertificate: SecCertificate? - let status = SecIdentityCopyCertificate(secIdentity, &secCertificate) - guard status == errSecSuccess, let secCertificate else { - throw StringError("failed to get certificate from SecIdentity: status \(status)") + init(secIdentity: SecIdentity) throws { + var secCertificate: SecCertificate? + let status = SecIdentityCopyCertificate(secIdentity, &secCertificate) + guard status == errSecSuccess, let secCertificate else { + throw StringError("failed to get certificate from SecIdentity: status \(status)") + } + self = try Certificate(secCertificate: secCertificate) } - self = try Certificate(secCertificate: secCertificate) } -} #endif extension Certificate { diff --git a/Sources/PackageSigning/embedded_resources.swift b/Sources/PackageSigning/embedded_resources.swift index a1dbeb69b2f..04e426ab004 100644 --- a/Sources/PackageSigning/embedded_resources.swift +++ b/Sources/PackageSigning/embedded_resources.swift @@ -1,13 +1,13 @@ struct PackageResources { -static let AppleWWDRCAG2_cer: [UInt8] = [48,130,2,247,48,130,2,124,160,3,2,1,2,2,8,111,239,216,245,233,163,167,238,48,10,6,8,42,134,72,206,61,4,3,2,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,51,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,30,23,13,49,52,48,53,48,54,50,51,52,51,50,52,90,23,13,50,57,48,53,48,54,50,51,52,51,50,52,90,48,129,128,49,52,48,50,6,3,85,4,3,12,43,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,65,32,45,32,71,50,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,89,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,3,66,0,4,221,240,183,6,75,207,221,115,4,19,196,67,137,3,147,128,251,94,246,116,173,66,97,82,88,2,38,83,25,200,99,34,7,9,82,97,202,196,217,87,239,109,38,104,139,116,145,140,196,249,128,104,40,252,9,104,240,16,218,233,208,46,201,26,163,129,247,48,129,244,48,70,6,8,43,6,1,5,5,7,1,1,4,58,48,56,48,54,6,8,43,6,1,5,5,7,48,1,134,42,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,52,45,97,112,112,108,101,114,111,111,116,99,97,103,51,48,29,6,3,85,29,14,4,22,4,20,132,182,132,204,58,134,98,114,22,89,148,232,26,163,189,72,223,58,223,11,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,31,6,3,85,29,35,4,24,48,22,128,20,187,176,222,161,88,51,136,154,164,138,153,222,190,189,235,175,218,203,36,171,48,55,6,3,85,29,31,4,48,48,46,48,44,160,42,160,40,134,38,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,97,112,112,108,101,114,111,111,116,99,97,103,51,46,99,114,108,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,15,4,2,5,0,48,10,6,8,42,134,72,206,61,4,3,2,3,105,0,48,102,2,49,0,217,177,199,49,198,35,246,79,77,208,217,71,197,125,24,105,17,135,113,39,211,104,173,224,155,101,154,190,108,223,63,70,166,144,9,190,110,161,59,44,176,81,137,65,60,135,210,191,2,49,0,252,100,82,137,75,60,93,191,107,28,194,137,152,47,114,174,181,155,170,26,11,35,84,119,84,232,21,67,162,197,18,218,151,80,115,124,94,208,110,178,92,98,80,215,81,241,58,90] -static let AppleWWDRCAG3_cer: [UInt8] = [48,130,4,81,48,130,3,57,160,3,2,1,2,2,16,124,175,105,10,37,183,57,254,123,155,68,122,193,120,197,238,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,48,48,50,49,57,49,56,49,51,52,55,90,23,13,51,48,48,50,50,48,48,48,48,48,48,48,90,48,117,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,11,48,9,6,3,85,4,11,12,2,71,51,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,216,245,137,252,168,89,11,135,199,76,145,46,45,86,144,211,120,29,164,48,233,165,72,239,11,67,191,45,132,251,36,93,69,27,229,235,89,54,18,92,84,100,158,108,98,45,180,198,151,202,204,60,246,214,6,145,252,229,2,166,28,106,180,121,213,103,203,172,233,63,7,17,225,132,188,71,29,102,142,57,162,232,180,73,237,58,210,225,16,96,122,142,147,140,202,192,218,12,192,131,208,227,249,145,214,167,140,200,193,115,226,174,70,209,98,157,146,168,144,96,55,125,104,150,205,141,224,252,155,250,120,187,227,123,175,45,23,221,91,254,128,89,35,117,23,184,18,193,237,27,229,52,206,254,34,181,158,73,176,229,85,191,143,132,162,60,168,186,197,134,149,22,228,0,201,159,3,208,204,179,58,22,123,214,5,92,157,235,71,174,13,181,45,140,14,105,77,64,208,75,76,59,4,158,141,33,177,172,46,67,84,48,206,193,138,134,148,152,75,223,106,13,63,254,251,28,174,151,23,194,120,10,48,224,95,31,84,59,73,183,37,0,26,55,130,210,86,151,165,82,73,124,96,56,155,239,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,9,254,192,21,144,249,175,100,10,146,18,185,38,40,99,12,151,236,167,178,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,3,130,1,1,0,173,101,19,232,246,224,129,119,68,2,71,66,190,95,165,57,32,234,98,169,253,197,144,201,115,19,213,158,155,208,170,15,141,141,203,237,1,207,108,40,64,91,199,85,36,65,248,252,207,193,181,35,233,220,236,241,111,202,128,29,119,194,196,97,73,37,103,175,15,202,57,37,173,211,227,122,204,51,40,13,14,46,161,87,64,115,250,230,92,174,6,81,41,237,227,133,12,79,97,220,50,22,139,119,208,68,202,93,114,3,49,70,156,174,155,64,26,250,244,224,211,62,250,47,140,102,159,151,196,84,89,239,210,72,244,7,153,73,96,89,25,199,221,148,209,192,193,108,127,120,33,239,12,235,59,108,153,130,75,82,96,56,181,57,130,109,236,82,49,83,190,15,145,76,73,73,116,143,166,81,203,132,71,78,29,117,39,110,189,249,210,92,243,127,194,108,11,9,54,226,100,228,194,55,3,20,25,213,234,106,148,170,169,219,254,246,154,8,103,139,239,43,184,170,23,73,131,175,207,203,188,233,207,234,149,113,176,180,69,162,204,229,135,170,10,195,65,58,121,92,218,80,52,157,149,59] -static let AppleWWDRCAG5_cer: [UInt8] = [48,130,4,85,48,130,3,61,160,3,2,1,2,2,20,59,126,128,10,238,211,2,161,230,236,219,151,217,202,172,40,156,241,105,148,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,48,49,50,49,54,49,57,51,56,53,54,90,23,13,51,48,49,50,49,48,48,48,48,48,48,48,90,48,117,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,11,48,9,6,3,85,4,11,12,2,71,53,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,159,93,218,31,251,250,188,208,75,34,60,199,214,38,250,23,247,244,159,30,62,100,17,102,154,239,94,190,171,52,189,170,44,33,110,214,30,148,33,133,44,116,193,14,16,97,170,60,99,74,126,74,227,200,117,214,207,194,156,8,72,123,106,185,41,177,201,102,253,200,138,22,209,178,4,60,130,186,128,108,226,255,10,114,235,172,254,59,111,72,190,158,139,17,77,149,125,178,123,144,47,2,28,78,252,73,190,215,111,181,79,190,120,198,218,222,178,205,201,217,102,17,59,90,233,9,69,115,137,80,212,78,226,104,5,126,218,117,156,75,1,174,218,227,207,109,116,77,222,83,208,213,26,56,130,58,208,157,227,93,41,123,177,129,234,41,39,11,251,96,124,134,18,251,240,98,79,6,231,76,209,31,217,109,158,237,115,218,120,33,13,157,112,217,70,87,144,95,103,132,193,115,119,10,168,98,98,182,174,112,134,187,117,35,137,173,121,246,230,164,212,253,131,38,50,10,59,36,146,91,32,161,156,209,47,128,24,155,221,60,11,231,181,253,236,128,87,15,23,158,63,43,135,39,187,247,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,25,139,151,141,74,91,97,120,87,244,165,92,53,18,138,57,8,227,176,117,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,3,130,1,1,0,90,196,53,162,217,230,10,158,82,162,0,130,34,119,205,114,47,144,249,34,175,20,37,204,170,10,66,96,146,194,189,117,29,235,76,202,21,229,126,107,64,16,94,251,91,69,116,13,240,122,125,136,145,206,222,99,139,66,137,210,24,223,65,179,88,158,6,8,135,72,221,64,175,35,213,237,235,44,96,229,235,164,127,28,233,156,131,214,148,95,76,98,57,138,78,174,19,141,125,67,184,220,94,172,190,24,64,242,230,15,44,93,19,147,241,123,101,168,194,104,72,222,255,180,150,155,12,251,50,54,158,158,13,149,95,56,10,139,150,210,18,108,183,139,11,142,215,62,236,111,1,170,206,77,69,96,219,132,113,102,98,229,25,101,48,205,138,255,69,83,251,110,251,136,119,67,195,72,99,249,247,81,179,114,94,121,226,86,207,188,187,132,185,56,90,120,174,17,72,82,187,13,53,139,148,222,204,116,154,104,245,73,96,148,172,242,168,179,21,134,144,208,204,48,67,134,211,229,112,2,81,180,129,192,168,151,212,234,234,176,140,9,64,239,56,147,178,205,34,3,235,103,67,101,200,69] -static let AppleRootCA_G2_cer: [UInt8] = [48,130,5,146,48,130,3,122,160,3,2,1,2,2,8,1,224,229,181,131,103,163,224,48,13,6,9,42,134,72,134,247,13,1,1,12,5,0,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,50,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,30,23,13,49,52,48,52,51,48,49,56,49,48,48,57,90,23,13,51,57,48,52,51,48,49,56,49,48,48,57,90,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,50,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,130,2,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,2,15,0,48,130,2,10,2,130,2,1,0,216,17,18,72,72,218,41,138,73,197,28,199,236,110,51,109,254,77,251,224,28,222,172,94,226,54,167,36,249,127,80,107,76,206,185,48,84,39,229,179,214,237,37,230,48,182,5,55,94,20,34,17,197,232,170,27,210,251,178,210,9,149,56,164,239,42,73,140,93,62,113,102,3,56,251,22,245,133,136,228,90,146,12,4,50,242,200,64,251,82,95,159,246,192,241,227,186,69,160,80,213,18,139,242,221,222,145,134,35,240,245,182,114,46,1,218,11,246,46,57,8,95,25,161,99,65,11,28,167,148,193,134,196,83,47,118,246,10,215,12,209,131,63,26,83,25,243,87,213,39,127,252,19,184,248,146,141,252,211,40,67,60,181,104,0,37,93,39,98,211,221,85,221,68,32,144,131,53,147,197,191,184,25,251,107,227,220,8,66,230,175,109,250,158,64,202,78,133,133,120,73,177,215,195,193,48,57,50,171,126,95,170,211,139,111,159,45,26,33,104,112,103,179,163,241,152,65,109,145,124,248,215,219,168,231,95,33,26,140,51,191,49,116,183,184,209,244,224,34,244,191,114,52,223,247,129,77,113,125,81,161,226,179,240,211,40,22,115,111,205,204,173,55,125,78,235,173,64,225,63,129,253,247,61,10,62,162,241,189,49,150,41,89,220,194,25,128,140,91,116,198,44,211,16,83,38,29,20,79,196,212,129,102,60,135,103,51,39,20,8,233,180,119,132,52,82,143,137,248,104,152,23,191,195,187,170,19,147,31,93,84,47,168,199,124,251,13,20,190,21,61,36,52,242,154,220,117,65,102,34,180,1,214,11,175,144,158,12,234,98,248,155,89,60,8,226,150,52,228,99,222,188,55,212,235,12,136,3,67,11,80,175,160,52,221,80,77,21,251,90,36,216,12,250,12,99,158,31,3,177,225,238,225,170,67,244,102,101,40,55,2,49,239,1,199,30,209,204,159,109,202,84,58,64,219,206,207,79,70,139,74,101,154,106,198,104,108,215,204,153,27,71,176,114,195,119,143,196,247,97,156,116,31,206,253,107,161,194,156,148,130,171,148,162,231,189,27,186,185,112,57,149,23,197,41,243,57,88,52,245,196,164,198,123,96,185,102,67,80,63,110,97,252,14,249,134,170,96,12,67,75,149,2,3,1,0,1,163,66,48,64,48,29,6,3,85,29,14,4,22,4,20,196,153,19,108,24,3,194,123,192,163,160,13,127,114,128,122,28,119,38,141,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,13,6,9,42,134,72,134,247,13,1,1,12,5,0,3,130,2,1,0,81,166,243,226,244,184,61,147,191,45,206,15,187,91,225,85,20,78,78,209,229,206,121,93,129,127,254,182,240,135,51,248,239,148,229,126,220,106,121,167,28,190,240,148,183,166,209,48,156,200,13,10,117,158,125,146,149,126,24,157,126,194,113,105,124,20,234,207,131,14,228,20,66,158,116,14,16,205,171,26,186,17,97,129,120,216,241,181,69,64,120,171,168,192,206,251,125,99,55,104,246,231,251,175,198,195,75,236,31,54,38,19,84,134,148,114,178,234,2,237,139,109,228,12,166,144,192,87,117,207,140,66,125,92,230,49,125,243,201,178,146,105,70,14,136,248,227,45,66,178,56,168,166,25,141,241,159,205,238,106,101,188,26,176,37,189,167,41,253,244,62,162,117,73,191,158,219,201,247,167,30,99,153,225,92,70,255,146,5,140,250,30,32,249,134,148,86,37,229,180,87,56,157,235,136,100,20,33,73,33,57,191,98,102,169,177,162,202,111,63,33,96,197,137,212,69,54,200,152,124,189,246,254,153,73,128,59,44,210,166,167,136,3,4,49,25,183,182,58,97,69,250,201,242,35,200,99,115,191,86,137,49,176,217,124,98,167,123,21,168,136,138,171,56,64,194,204,18,255,21,227,240,55,223,55,114,203,204,152,230,191,162,188,250,38,138,113,86,215,231,36,27,72,68,62,158,252,159,201,204,26,236,67,60,1,188,52,120,200,105,245,198,230,86,236,6,9,54,144,235,20,74,27,94,201,136,35,218,3,48,145,11,184,54,62,249,231,181,40,111,190,63,236,60,143,101,29,229,192,30,135,164,170,186,152,253,146,227,108,38,119,221,6,180,100,6,135,244,78,214,186,74,170,22,168,244,5,103,102,150,186,226,85,121,195,44,93,73,143,128,73,43,138,18,199,118,128,81,223,186,189,101,93,62,55,71,99,49,233,229,244,197,63,75,173,4,138,122,113,44,175,9,67,55,15,168,227,50,79,244,69,182,109,151,54,236,132,245,10,1,234,23,187,133,141,66,147,112,195,80,229,20,139,191,63,195,65,15,221,34,4,35,8,138,186,109,113,68,171,115,9,58,201,249,82,128,9,223,186,233,230,22,202,46,46,76,178,211,220,229,4,84,178,212,52,128,50,181,188,15,23,225] -static let AppleComputerRootCertificate_cer: [UInt8] = [48,130,5,186,48,130,4,162,160,3,2,1,2,2,1,1,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,129,134,49,11,48,9,6,3,85,4,6,19,2,85,83,49,29,48,27,6,3,85,4,10,19,20,65,112,112,108,101,32,67,111,109,112,117,116,101,114,44,32,73,110,99,46,49,45,48,43,6,3,85,4,11,19,36,65,112,112,108,101,32,67,111,109,112,117,116,101,114,32,67,101,114,116,105,102,105,99,97,116,101,32,65,117,116,104,111,114,105,116,121,49,41,48,39,6,3,85,4,3,19,32,65,112,112,108,101,32,82,111,111,116,32,67,101,114,116,105,102,105,99,97,116,101,32,65,117,116,104,111,114,105,116,121,48,30,23,13,48,53,48,50,49,48,48,48,49,56,49,52,90,23,13,50,53,48,50,49,48,48,48,49,56,49,52,90,48,129,134,49,11,48,9,6,3,85,4,6,19,2,85,83,49,29,48,27,6,3,85,4,10,19,20,65,112,112,108,101,32,67,111,109,112,117,116,101,114,44,32,73,110,99,46,49,45,48,43,6,3,85,4,11,19,36,65,112,112,108,101,32,67,111,109,112,117,116,101,114,32,67,101,114,116,105,102,105,99,97,116,101,32,65,117,116,104,111,114,105,116,121,49,41,48,39,6,3,85,4,3,19,32,65,112,112,108,101,32,82,111,111,116,32,67,101,114,116,105,102,105,99,97,116,101,32,65,117,116,104,111,114,105,116,121,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,228,145,169,9,31,145,219,30,71,80,235,5,237,94,121,132,45,235,54,162,87,76,85,236,139,25,137,222,249,75,108,245,7,171,34,48,2,232,24,62,248,80,9,211,127,65,168,152,249,209,202,102,156,36,107,17,208,163,187,228,27,42,195,31,149,158,122,12,164,71,139,91,212,22,55,51,203,196,15,77,206,20,105,209,201,25,114,245,93,14,213,127,95,155,242,37,3,186,85,143,77,93,13,241,100,53,35,21,75,21,89,29,179,148,247,246,156,158,207,80,186,193,88,80,103,143,8,180,32,247,203,172,44,32,111,112,182,63,1,48,140,183,67,207,15,157,61,243,43,73,40,26,200,254,206,181,185,14,217,94,28,214,203,61,181,58,173,244,15,14,0,146,11,177,33,22,46,116,213,60,13,219,98,22,171,163,113,146,71,83,85,193,175,47,65,179,248,251,227,112,205,230,163,76,69,126,31,76,107,80,150,65,137,196,116,98,11,16,131,65,135,51,138,129,177,48,88,236,90,4,50,140,104,179,143,29,222,101,115,255,103,94,101,188,73,216,118,159,51,20,101,161,119,148,201,45,2,3,1,0,1,163,130,2,47,48,130,2,43,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,29,6,3,85,29,14,4,22,4,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,130,1,41,6,3,85,29,32,4,130,1,32,48,130,1,28,48,130,1,24,6,9,42,134,72,134,247,99,100,5,1,48,130,1,9,48,65,6,8,43,6,1,5,5,7,2,1,22,53,104,116,116,112,115,58,47,47,119,119,119,46,97,112,112,108,101,46,99,111,109,47,99,101,114,116,105,102,105,99,97,116,101,97,117,116,104,111,114,105,116,121,47,116,101,114,109,115,46,104,116,109,108,48,129,195,6,8,43,6,1,5,5,7,2,2,48,129,182,26,129,179,82,101,108,105,97,110,99,101,32,111,110,32,116,104,105,115,32,99,101,114,116,105,102,105,99,97,116,101,32,98,121,32,97,110,121,32,112,97,114,116,121,32,97,115,115,117,109,101,115,32,97,99,99,101,112,116,97,110,99,101,32,111,102,32,116,104,101,32,116,104,101,110,32,97,112,112,108,105,99,97,98,108,101,32,115,116,97,110,100,97,114,100,32,116,101,114,109,115,32,97,110,100,32,99,111,110,100,105,116,105,111,110,115,32,111,102,32,117,115,101,44,32,99,101,114,116,105,102,105,99,97,116,101,32,112,111,108,105,99,121,32,97,110,100,32,99,101,114,116,105,102,105,99,97,116,105,111,110,32,112,114,97,99,116,105,99,101,32,115,116,97,116,101,109,101,110,116,115,46,48,68,6,3,85,29,31,4,61,48,59,48,57,160,55,160,53,134,51,104,116,116,112,115,58,47,47,119,119,119,46,97,112,112,108,101,46,99,111,109,47,99,101,114,116,105,102,105,99,97,116,101,97,117,116,104,111,114,105,116,121,47,114,111,111,116,46,99,114,108,48,85,6,8,43,6,1,5,5,7,1,1,4,73,48,71,48,69,6,8,43,6,1,5,5,7,48,2,134,57,104,116,116,112,115,58,47,47,119,119,119,46,97,112,112,108,101,46,99,111,109,47,99,101,114,116,105,102,105,99,97,116,101,97,117,116,104,111,114,105,116,121,47,99,97,115,105,103,110,101,114,115,46,104,116,109,108,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,130,1,1,0,157,218,45,40,88,47,125,118,4,185,4,211,62,206,183,102,99,78,143,47,212,254,75,173,114,189,163,57,198,82,77,5,152,82,245,137,81,1,36,121,190,26,50,247,229,68,139,75,68,7,57,130,214,90,202,180,32,94,217,174,21,93,29,140,29,50,191,56,49,98,72,93,199,225,144,177,248,36,64,248,95,88,155,81,93,87,157,193,229,255,60,204,114,33,110,196,233,233,161,119,215,44,23,38,195,63,235,154,232,11,3,186,233,179,74,114,235,51,9,91,173,230,98,49,106,232,175,47,213,175,30,87,118,143,127,55,45,46,2,92,221,99,201,242,113,184,38,64,223,21,141,117,68,63,121,189,230,29,153,225,67,44,62,173,111,190,185,164,254,14,53,25,81,99,177,195,222,181,146,62,81,120,1,115,138,164,35,202,164,136,241,30,92,31,65,22,45,126,149,10,170,233,137,65,152,27,26,221,203,32,191,71,94,12,38,197,85,53,77,198,48,139,153,103,20,199,9,31,186,71,199,218,1,9,135,36,66,149,189,19,96,25,10,239,234,127,14,110,205,193,68,67,58,74,213,227] -static let AppleWWDRCAG7_cer: [UInt8] = [48,130,4,85,48,130,3,61,160,3,2,1,2,2,20,52,24,88,255,1,254,6,63,142,241,159,31,233,60,1,180,193,70,255,201,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,50,49,49,49,55,50,48,52,48,53,51,90,23,13,50,51,49,49,49,55,50,48,52,48,53,50,90,48,117,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,11,12,2,71,55,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,172,174,209,211,182,138,177,27,40,149,173,222,81,81,76,63,51,225,78,92,175,179,252,2,210,101,79,42,212,116,104,140,117,23,101,207,40,228,72,9,152,113,82,50,44,22,78,120,142,146,86,100,169,221,139,205,226,212,199,59,162,18,69,55,2,25,98,100,47,127,97,198,211,89,34,191,171,249,20,163,237,182,158,153,186,47,241,177,220,48,66,79,182,182,178,198,116,170,98,86,187,237,68,54,15,209,229,32,116,147,87,58,93,158,220,1,252,120,111,105,22,53,195,110,1,194,158,114,212,113,54,177,118,9,122,190,13,42,151,241,176,94,11,27,18,173,43,171,7,223,99,45,245,136,233,50,18,162,85,88,67,118,60,61,23,128,31,41,219,177,169,159,171,150,5,157,21,220,221,219,78,15,231,19,124,90,43,46,2,65,246,238,122,106,182,115,96,247,151,25,20,139,149,51,56,147,218,0,37,54,174,85,90,124,159,249,244,98,4,7,116,233,29,167,149,87,35,172,43,36,218,100,79,40,114,233,150,176,8,60,136,27,20,99,67,215,137,174,152,193,242,45,142,227,81,37,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,93,66,16,108,27,187,199,82,151,78,68,189,19,39,185,58,18,119,131,43,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,130,1,1,0,82,163,8,41,19,101,183,181,31,230,52,3,237,246,24,119,188,61,202,39,181,112,236,236,108,51,75,246,153,37,148,7,158,33,51,3,106,245,125,10,46,43,223,8,169,130,222,74,127,225,231,11,75,5,184,39,152,73,221,193,12,134,215,129,100,174,130,156,196,69,241,234,143,28,34,48,227,162,37,97,68,137,254,133,122,86,240,114,146,124,12,68,84,36,183,181,164,159,38,240,50,249,87,157,106,121,108,64,237,15,52,6,6,66,255,216,14,49,101,109,230,46,1,217,6,191,197,202,13,174,71,212,5,23,136,60,233,156,228,25,100,109,138,148,173,17,220,1,246,229,120,175,173,232,112,215,13,93,129,62,70,42,44,174,36,161,199,210,224,125,191,29,245,54,107,197,222,169,10,154,128,177,17,94,178,100,126,179,193,87,204,194,108,89,153,183,244,176,221,49,218,72,214,106,129,238,178,139,80,53,22,230,231,92,113,98,110,176,242,81,226,168,109,248,42,203,104,115,198,166,196,26,67,73,1,62,169,169,0,138,134,108,131,136,210,92,112,87,122,218,248,118,204,25,213,176] -static let AppleIncRootCertificate_cer: [UInt8] = [48,130,4,187,48,130,3,163,160,3,2,1,2,2,1,2,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,48,54,48,52,50,53,50,49,52,48,51,54,90,23,13,51,53,48,50,48,57,50,49,52,48,51,54,90,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,228,145,169,9,31,145,219,30,71,80,235,5,237,94,121,132,45,235,54,162,87,76,85,236,139,25,137,222,249,75,108,245,7,171,34,48,2,232,24,62,248,80,9,211,127,65,168,152,249,209,202,102,156,36,107,17,208,163,187,228,27,42,195,31,149,158,122,12,164,71,139,91,212,22,55,51,203,196,15,77,206,20,105,209,201,25,114,245,93,14,213,127,95,155,242,37,3,186,85,143,77,93,13,241,100,53,35,21,75,21,89,29,179,148,247,246,156,158,207,80,186,193,88,80,103,143,8,180,32,247,203,172,44,32,111,112,182,63,1,48,140,183,67,207,15,157,61,243,43,73,40,26,200,254,206,181,185,14,217,94,28,214,203,61,181,58,173,244,15,14,0,146,11,177,33,22,46,116,213,60,13,219,98,22,171,163,113,146,71,83,85,193,175,47,65,179,248,251,227,112,205,230,163,76,69,126,31,76,107,80,150,65,137,196,116,98,11,16,131,65,135,51,138,129,177,48,88,236,90,4,50,140,104,179,143,29,222,101,115,255,103,94,101,188,73,216,118,159,51,20,101,161,119,148,201,45,2,3,1,0,1,163,130,1,122,48,130,1,118,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,29,6,3,85,29,14,4,22,4,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,130,1,17,6,3,85,29,32,4,130,1,8,48,130,1,4,48,130,1,0,6,9,42,134,72,134,247,99,100,5,1,48,129,242,48,42,6,8,43,6,1,5,5,7,2,1,22,30,104,116,116,112,115,58,47,47,119,119,119,46,97,112,112,108,101,46,99,111,109,47,97,112,112,108,101,99,97,47,48,129,195,6,8,43,6,1,5,5,7,2,2,48,129,182,26,129,179,82,101,108,105,97,110,99,101,32,111,110,32,116,104,105,115,32,99,101,114,116,105,102,105,99,97,116,101,32,98,121,32,97,110,121,32,112,97,114,116,121,32,97,115,115,117,109,101,115,32,97,99,99,101,112,116,97,110,99,101,32,111,102,32,116,104,101,32,116,104,101,110,32,97,112,112,108,105,99,97,98,108,101,32,115,116,97,110,100,97,114,100,32,116,101,114,109,115,32,97,110,100,32,99,111,110,100,105,116,105,111,110,115,32,111,102,32,117,115,101,44,32,99,101,114,116,105,102,105,99,97,116,101,32,112,111,108,105,99,121,32,97,110,100,32,99,101,114,116,105,102,105,99,97,116,105,111,110,32,112,114,97,99,116,105,99,101,32,115,116,97,116,101,109,101,110,116,115,46,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,130,1,1,0,92,54,153,76,45,120,183,237,140,155,220,243,119,155,242,118,210,119,48,79,193,31,133,131,133,27,153,61,71,55,242,169,155,64,142,44,212,177,144,18,216,190,244,115,155,238,210,100,15,203,121,79,52,216,162,62,249,120,255,107,200,7,236,125,57,131,139,83,32,211,56,196,177,191,154,79,10,107,255,43,252,89,167,5,9,124,23,64,86,17,30,116,211,183,139,35,59,71,163,213,111,36,226,235,209,183,112,223,15,69,225,39,202,241,109,120,237,231,181,23,23,168,220,126,34,53,202,37,213,217,15,214,107,212,162,36,35,17,247,161,172,143,115,129,96,198,27,91,9,47,146,178,248,68,72,240,96,56,158,21,245,61,38,103,32,138,51,106,247,13,130,207,222,235,163,47,249,83,106,91,100,192,99,51,119,247,58,7,44,86,235,218,15,33,14,218,186,115,25,79,181,217,54,127,193,135,85,217,167,153,185,50,66,251,216,213,113,158,126,161,82,183,27,189,147,66,36,18,42,199,15,29,182,77,156,94,99,200,75,128,23,80,170,138,213,218,228,252,208,9,7,55,176,117,117,33] -static let AppleWWDRCAG4_cer: [UInt8] = [48,130,4,85,48,130,3,61,160,3,2,1,2,2,20,19,220,119,149,82,113,229,61,198,50,232,204,255,229,33,243,204,197,206,210,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,48,49,50,49,54,49,57,51,54,48,52,90,23,13,51,48,49,50,49,48,48,48,48,48,48,48,90,48,117,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,11,48,9,6,3,85,4,11,12,2,71,52,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,208,31,120,170,122,39,50,176,70,95,231,23,118,216,160,157,14,41,142,173,61,50,165,196,107,55,201,228,65,145,106,183,121,113,93,12,52,4,96,117,247,174,67,143,71,196,134,30,8,232,191,214,57,82,47,30,103,252,113,241,130,109,60,126,6,82,118,157,44,188,213,67,233,177,180,188,64,58,120,81,93,81,161,37,225,190,108,145,157,107,33,89,24,65,213,15,141,109,65,42,57,74,33,224,144,159,78,19,79,208,140,154,50,184,215,106,146,30,37,106,164,50,206,34,25,133,5,96,220,2,74,242,90,235,119,121,2,125,192,151,84,108,146,142,118,1,230,70,143,229,230,42,251,162,176,173,24,173,109,51,133,56,35,139,234,138,150,237,159,174,102,79,163,12,64,39,109,149,208,98,136,217,67,41,39,253,237,164,191,83,46,144,21,101,60,217,46,98,100,51,29,108,106,221,142,33,170,164,95,21,198,48,237,95,230,140,54,146,148,183,220,57,2,0,251,100,140,212,12,129,242,63,213,52,151,135,117,38,194,111,174,3,99,33,12,123,212,27,177,98,197,2,156,189,253,175,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,91,217,250,29,231,154,26,11,163,153,118,34,80,134,62,145,200,91,119,168,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,3,130,1,1,0,63,86,61,158,229,182,195,121,230,69,32,104,189,191,115,139,44,18,158,2,227,174,128,34,140,4,30,195,82,200,112,128,168,251,206,167,176,213,66,68,130,3,130,79,6,252,59,73,20,251,216,116,82,133,175,167,157,33,231,1,18,3,159,205,64,88,208,1,215,191,50,131,43,83,88,40,60,238,156,159,84,118,61,100,39,198,126,141,29,56,77,45,174,129,230,185,165,184,156,137,148,247,159,199,135,165,81,102,52,27,57,113,57,36,227,135,103,239,165,177,104,123,140,238,61,247,174,182,123,226,210,255,223,97,198,106,117,73,149,34,68,168,4,252,148,184,11,46,57,17,73,18,209,229,129,234,89,0,79,91,60,90,54,218,122,34,115,9,9,105,205,192,124,234,226,36,254,152,68,184,248,239,178,113,63,26,93,212,93,126,51,77,156,29,36,190,0,240,144,3,88,153,65,61,49,90,98,64,175,57,168,81,67,146,171,4,168,156,194,77,177,75,210,171,124,74,95,235,157,59,188,79,136,64,6,19,255,144,23,138,8,71,41,232,98,152,41,165,79,17,5,105,58,207,242,159] -static let AppleWWDRCAG6_cer: [UInt8] = [48,130,3,22,48,130,2,156,160,3,2,1,2,2,20,34,193,161,71,10,116,115,105,239,83,134,18,201,198,159,61,56,243,108,215,48,10,6,8,42,134,72,206,61,4,3,3,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,51,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,30,23,13,50,49,48,51,49,55,50,48,51,55,49,48,90,23,13,51,54,48,51,49,57,48,48,48,48,48,48,90,48,117,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,11,48,9,6,3,85,4,11,12,2,71,54,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,118,48,16,6,7,42,134,72,206,61,2,1,6,5,43,129,4,0,34,3,98,0,4,110,196,10,11,222,15,174,85,166,101,121,215,130,220,115,117,82,75,241,61,18,25,137,224,13,17,169,158,9,247,55,163,211,240,147,4,111,177,67,139,134,193,152,248,66,157,157,255,178,174,143,23,247,6,112,165,214,176,190,111,58,215,145,135,34,120,231,29,192,72,254,220,56,31,154,106,143,116,125,202,113,74,255,196,100,86,231,136,6,205,129,145,161,34,26,72,163,129,250,48,129,247,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,187,176,222,161,88,51,136,154,164,138,153,222,190,189,235,175,218,203,36,171,48,70,6,8,43,6,1,5,5,7,1,1,4,58,48,56,48,54,6,8,43,6,1,5,5,7,48,1,134,42,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,103,51,48,55,6,3,85,29,31,4,48,48,46,48,44,160,42,160,40,134,38,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,97,112,112,108,101,114,111,111,116,99,97,103,51,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,63,47,148,35,81,211,80,201,154,40,61,237,176,124,229,207,165,144,98,153,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,10,6,8,42,134,72,206,61,4,3,3,3,104,0,48,101,2,48,64,94,20,170,228,140,138,162,3,2,62,220,56,247,64,90,7,174,251,9,161,6,37,123,159,64,31,196,169,145,157,232,36,163,136,43,78,158,227,19,109,117,87,155,28,92,197,249,2,49,0,211,72,252,90,173,149,239,54,185,49,83,116,228,80,194,55,223,44,239,21,85,81,79,140,49,88,144,189,247,131,172,117,198,120,249,17,141,177,128,242,71,152,38,118,189,39,12,104] -static let AppleWWDRCAG8_cer: [UInt8] = [48,130,4,85,48,130,3,61,160,3,2,1,2,2,20,84,181,11,175,121,13,141,127,140,175,104,76,86,47,80,105,10,26,186,95,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,51,48,54,50,48,50,51,51,55,49,53,90,23,13,50,53,48,49,50,52,48,48,48,48,48,48,90,48,117,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,11,12,2,71,56,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,208,64,16,212,8,249,82,33,99,79,60,104,247,212,156,130,2,140,131,104,188,183,141,127,136,231,66,77,44,239,34,165,194,137,222,189,12,215,77,97,80,45,57,228,48,115,165,210,213,104,154,51,242,239,217,42,173,46,31,3,186,248,165,241,66,11,87,46,70,198,208,88,211,112,95,247,178,55,239,106,31,62,191,137,57,194,173,254,245,5,251,88,150,49,200,135,44,213,35,186,117,176,44,245,171,160,186,242,32,12,76,235,36,99,105,233,34,64,240,142,88,91,222,100,123,137,27,81,18,4,224,23,178,89,205,223,241,231,206,175,44,50,232,105,193,208,8,126,29,162,71,115,209,75,59,253,185,133,220,71,167,40,130,121,41,72,137,2,40,226,193,236,44,31,91,134,252,216,182,203,113,192,115,1,75,252,5,17,17,108,1,3,52,90,246,129,194,94,31,124,20,14,222,63,107,33,203,79,245,215,97,230,132,3,146,188,231,37,41,158,205,91,12,193,219,227,196,58,217,118,87,172,47,56,20,25,200,183,177,162,85,79,95,78,142,25,89,169,218,253,114,218,176,4,33,5,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,181,189,188,128,196,12,227,56,164,244,183,173,35,179,239,68,206,185,90,133,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,130,1,1,0,76,179,235,122,57,148,74,149,102,250,22,49,234,13,138,143,93,66,56,198,7,205,232,201,34,172,252,8,66,126,95,147,95,49,42,168,34,193,118,25,43,238,174,114,233,189,86,207,73,36,146,8,247,205,25,117,195,249,26,39,13,14,220,41,141,63,182,219,165,79,76,114,196,96,145,137,17,126,36,149,67,34,96,103,188,223,255,171,229,60,22,23,157,130,20,78,157,244,117,254,80,185,173,5,178,184,121,246,149,214,16,229,246,83,244,207,35,230,119,15,236,184,75,105,248,226,158,2,49,217,142,217,202,190,99,94,95,225,160,105,206,193,205,110,73,163,120,97,175,57,60,106,75,10,52,37,100,213,48,181,60,171,221,17,129,57,113,232,192,195,88,128,17,16,26,17,210,194,188,89,240,138,217,53,115,192,230,109,228,201,125,98,20,62,130,2,169,16,105,55,121,97,111,240,70,148,62,53,245,171,172,99,208,216,94,89,87,105,209,184,75,110,93,212,95,19,156,112,78,37,17,220,36,44,30,22,158,150,90,4,237,69,238,58,238,103,93,143,195,134,176,245,76,31,104,16] -static let AppleRootCA_G3_cer: [UInt8] = [48,130,2,67,48,130,1,201,160,3,2,1,2,2,8,45,197,252,136,210,197,75,149,48,10,6,8,42,134,72,206,61,4,3,3,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,51,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,30,23,13,49,52,48,52,51,48,49,56,49,57,48,54,90,23,13,51,57,48,52,51,48,49,56,49,57,48,54,90,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,51,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,118,48,16,6,7,42,134,72,206,61,2,1,6,5,43,129,4,0,34,3,98,0,4,152,233,47,61,64,114,164,237,147,34,114,129,19,28,221,16,149,241,197,163,78,113,220,20,22,217,14,229,166,5,42,119,100,123,95,78,56,211,187,28,68,181,127,245,31,182,50,98,93,201,233,132,91,79,48,79,17,90,0,253,88,88,12,165,245,15,44,77,7,71,19,117,218,151,151,151,111,49,92,237,43,157,123,32,59,216,185,84,217,94,153,164,58,81,10,49,163,66,48,64,48,29,6,3,85,29,14,4,22,4,20,187,176,222,161,88,51,136,154,164,138,153,222,190,189,235,175,218,203,36,171,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,10,6,8,42,134,72,206,61,4,3,3,3,104,0,48,101,2,49,0,131,233,193,196,22,94,26,93,52,24,217,237,239,244,108,14,0,70,75,184,223,178,70,17,197,15,253,230,122,140,161,166,107,206,194,3,212,156,245,147,198,116,184,106,223,170,35,21,2,48,109,102,138,16,202,212,13,212,79,205,141,67,62,180,138,99,165,51,110,227,109,218,23,183,100,31,200,83,38,249,136,98,116,57,11,23,91,203,81,168,12,232,24,3,231,162,178,40] -} \ No newline at end of file + static let AppleWWDRCAG2_cer: [UInt8] = [48, 130, 2, 247, 48, 130, 2, 124, 160, 3, 2, 1, 2, 2, 8, 111, 239, 216, 245, 233, 163, 167, 238, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 30, 23, 13, 49, 52, 48, 53, 48, 54, 50, 51, 52, 51, 50, 52, 90, 23, 13, 50, 57, 48, 53, 48, 54, 50, 51, 52, 51, 50, 52, 90, 48, 129, 128, 49, 52, 48, 50, 6, 3, 85, 4, 3, 12, 43, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 65, 32, 45, 32, 71, 50, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 221, 240, 183, 6, 75, 207, 221, 115, 4, 19, 196, 67, 137, 3, 147, 128, 251, 94, 246, 116, 173, 66, 97, 82, 88, 2, 38, 83, 25, 200, 99, 34, 7, 9, 82, 97, 202, 196, 217, 87, 239, 109, 38, 104, 139, 116, 145, 140, 196, 249, 128, 104, 40, 252, 9, 104, 240, 16, 218, 233, 208, 46, 201, 26, 163, 129, 247, 48, 129, 244, 48, 70, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 58, 48, 56, 48, 54, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 42, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 52, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 103, 51, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 132, 182, 132, 204, 58, 134, 98, 114, 22, 89, 148, 232, 26, 163, 189, 72, 223, 58, 223, 11, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 187, 176, 222, 161, 88, 51, 136, 154, 164, 138, 153, 222, 190, 189, 235, 175, 218, 203, 36, 171, 48, 55, 6, 3, 85, 29, 31, 4, 48, 48, 46, 48, 44, 160, 42, 160, 40, 134, 38, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 103, 51, 46, 99, 114, 108, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 15, 4, 2, 5, 0, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 105, 0, 48, 102, 2, 49, 0, 217, 177, 199, 49, 198, 35, 246, 79, 77, 208, 217, 71, 197, 125, 24, 105, 17, 135, 113, 39, 211, 104, 173, 224, 155, 101, 154, 190, 108, 223, 63, 70, 166, 144, 9, 190, 110, 161, 59, 44, 176, 81, 137, 65, 60, 135, 210, 191, 2, 49, 0, 252, 100, 82, 137, 75, 60, 93, 191, 107, 28, 194, 137, 152, 47, 114, 174, 181, 155, 170, 26, 11, 35, 84, 119, 84, 232, 21, 67, 162, 197, 18, 218, 151, 80, 115, 124, 94, 208, 110, 178, 92, 98, 80, 215, 81, 241, 58, 90] + static let AppleWWDRCAG3_cer: [UInt8] = [48, 130, 4, 81, 48, 130, 3, 57, 160, 3, 2, 1, 2, 2, 16, 124, 175, 105, 10, 37, 183, 57, 254, 123, 155, 68, 122, 193, 120, 197, 238, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 48, 48, 50, 49, 57, 49, 56, 49, 51, 52, 55, 90, 23, 13, 51, 48, 48, 50, 50, 48, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 51, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 216, 245, 137, 252, 168, 89, 11, 135, 199, 76, 145, 46, 45, 86, 144, 211, 120, 29, 164, 48, 233, 165, 72, 239, 11, 67, 191, 45, 132, 251, 36, 93, 69, 27, 229, 235, 89, 54, 18, 92, 84, 100, 158, 108, 98, 45, 180, 198, 151, 202, 204, 60, 246, 214, 6, 145, 252, 229, 2, 166, 28, 106, 180, 121, 213, 103, 203, 172, 233, 63, 7, 17, 225, 132, 188, 71, 29, 102, 142, 57, 162, 232, 180, 73, 237, 58, 210, 225, 16, 96, 122, 142, 147, 140, 202, 192, 218, 12, 192, 131, 208, 227, 249, 145, 214, 167, 140, 200, 193, 115, 226, 174, 70, 209, 98, 157, 146, 168, 144, 96, 55, 125, 104, 150, 205, 141, 224, 252, 155, 250, 120, 187, 227, 123, 175, 45, 23, 221, 91, 254, 128, 89, 35, 117, 23, 184, 18, 193, 237, 27, 229, 52, 206, 254, 34, 181, 158, 73, 176, 229, 85, 191, 143, 132, 162, 60, 168, 186, 197, 134, 149, 22, 228, 0, 201, 159, 3, 208, 204, 179, 58, 22, 123, 214, 5, 92, 157, 235, 71, 174, 13, 181, 45, 140, 14, 105, 77, 64, 208, 75, 76, 59, 4, 158, 141, 33, 177, 172, 46, 67, 84, 48, 206, 193, 138, 134, 148, 152, 75, 223, 106, 13, 63, 254, 251, 28, 174, 151, 23, 194, 120, 10, 48, 224, 95, 31, 84, 59, 73, 183, 37, 0, 26, 55, 130, 210, 86, 151, 165, 82, 73, 124, 96, 56, 155, 239, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 9, 254, 192, 21, 144, 249, 175, 100, 10, 146, 18, 185, 38, 40, 99, 12, 151, 236, 167, 178, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, 173, 101, 19, 232, 246, 224, 129, 119, 68, 2, 71, 66, 190, 95, 165, 57, 32, 234, 98, 169, 253, 197, 144, 201, 115, 19, 213, 158, 155, 208, 170, 15, 141, 141, 203, 237, 1, 207, 108, 40, 64, 91, 199, 85, 36, 65, 248, 252, 207, 193, 181, 35, 233, 220, 236, 241, 111, 202, 128, 29, 119, 194, 196, 97, 73, 37, 103, 175, 15, 202, 57, 37, 173, 211, 227, 122, 204, 51, 40, 13, 14, 46, 161, 87, 64, 115, 250, 230, 92, 174, 6, 81, 41, 237, 227, 133, 12, 79, 97, 220, 50, 22, 139, 119, 208, 68, 202, 93, 114, 3, 49, 70, 156, 174, 155, 64, 26, 250, 244, 224, 211, 62, 250, 47, 140, 102, 159, 151, 196, 84, 89, 239, 210, 72, 244, 7, 153, 73, 96, 89, 25, 199, 221, 148, 209, 192, 193, 108, 127, 120, 33, 239, 12, 235, 59, 108, 153, 130, 75, 82, 96, 56, 181, 57, 130, 109, 236, 82, 49, 83, 190, 15, 145, 76, 73, 73, 116, 143, 166, 81, 203, 132, 71, 78, 29, 117, 39, 110, 189, 249, 210, 92, 243, 127, 194, 108, 11, 9, 54, 226, 100, 228, 194, 55, 3, 20, 25, 213, 234, 106, 148, 170, 169, 219, 254, 246, 154, 8, 103, 139, 239, 43, 184, 170, 23, 73, 131, 175, 207, 203, 188, 233, 207, 234, 149, 113, 176, 180, 69, 162, 204, 229, 135, 170, 10, 195, 65, 58, 121, 92, 218, 80, 52, 157, 149, 59] + static let AppleWWDRCAG5_cer: [UInt8] = [48, 130, 4, 85, 48, 130, 3, 61, 160, 3, 2, 1, 2, 2, 20, 59, 126, 128, 10, 238, 211, 2, 161, 230, 236, 219, 151, 217, 202, 172, 40, 156, 241, 105, 148, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 48, 49, 50, 49, 54, 49, 57, 51, 56, 53, 54, 90, 23, 13, 51, 48, 49, 50, 49, 48, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 53, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 159, 93, 218, 31, 251, 250, 188, 208, 75, 34, 60, 199, 214, 38, 250, 23, 247, 244, 159, 30, 62, 100, 17, 102, 154, 239, 94, 190, 171, 52, 189, 170, 44, 33, 110, 214, 30, 148, 33, 133, 44, 116, 193, 14, 16, 97, 170, 60, 99, 74, 126, 74, 227, 200, 117, 214, 207, 194, 156, 8, 72, 123, 106, 185, 41, 177, 201, 102, 253, 200, 138, 22, 209, 178, 4, 60, 130, 186, 128, 108, 226, 255, 10, 114, 235, 172, 254, 59, 111, 72, 190, 158, 139, 17, 77, 149, 125, 178, 123, 144, 47, 2, 28, 78, 252, 73, 190, 215, 111, 181, 79, 190, 120, 198, 218, 222, 178, 205, 201, 217, 102, 17, 59, 90, 233, 9, 69, 115, 137, 80, 212, 78, 226, 104, 5, 126, 218, 117, 156, 75, 1, 174, 218, 227, 207, 109, 116, 77, 222, 83, 208, 213, 26, 56, 130, 58, 208, 157, 227, 93, 41, 123, 177, 129, 234, 41, 39, 11, 251, 96, 124, 134, 18, 251, 240, 98, 79, 6, 231, 76, 209, 31, 217, 109, 158, 237, 115, 218, 120, 33, 13, 157, 112, 217, 70, 87, 144, 95, 103, 132, 193, 115, 119, 10, 168, 98, 98, 182, 174, 112, 134, 187, 117, 35, 137, 173, 121, 246, 230, 164, 212, 253, 131, 38, 50, 10, 59, 36, 146, 91, 32, 161, 156, 209, 47, 128, 24, 155, 221, 60, 11, 231, 181, 253, 236, 128, 87, 15, 23, 158, 63, 43, 135, 39, 187, 247, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 25, 139, 151, 141, 74, 91, 97, 120, 87, 244, 165, 92, 53, 18, 138, 57, 8, 227, 176, 117, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, 90, 196, 53, 162, 217, 230, 10, 158, 82, 162, 0, 130, 34, 119, 205, 114, 47, 144, 249, 34, 175, 20, 37, 204, 170, 10, 66, 96, 146, 194, 189, 117, 29, 235, 76, 202, 21, 229, 126, 107, 64, 16, 94, 251, 91, 69, 116, 13, 240, 122, 125, 136, 145, 206, 222, 99, 139, 66, 137, 210, 24, 223, 65, 179, 88, 158, 6, 8, 135, 72, 221, 64, 175, 35, 213, 237, 235, 44, 96, 229, 235, 164, 127, 28, 233, 156, 131, 214, 148, 95, 76, 98, 57, 138, 78, 174, 19, 141, 125, 67, 184, 220, 94, 172, 190, 24, 64, 242, 230, 15, 44, 93, 19, 147, 241, 123, 101, 168, 194, 104, 72, 222, 255, 180, 150, 155, 12, 251, 50, 54, 158, 158, 13, 149, 95, 56, 10, 139, 150, 210, 18, 108, 183, 139, 11, 142, 215, 62, 236, 111, 1, 170, 206, 77, 69, 96, 219, 132, 113, 102, 98, 229, 25, 101, 48, 205, 138, 255, 69, 83, 251, 110, 251, 136, 119, 67, 195, 72, 99, 249, 247, 81, 179, 114, 94, 121, 226, 86, 207, 188, 187, 132, 185, 56, 90, 120, 174, 17, 72, 82, 187, 13, 53, 139, 148, 222, 204, 116, 154, 104, 245, 73, 96, 148, 172, 242, 168, 179, 21, 134, 144, 208, 204, 48, 67, 134, 211, 229, 112, 2, 81, 180, 129, 192, 168, 151, 212, 234, 234, 176, 140, 9, 64, 239, 56, 147, 178, 205, 34, 3, 235, 103, 67, 101, 200, 69] + static let AppleRootCA_G2_cer: [UInt8] = [48, 130, 5, 146, 48, 130, 3, 122, 160, 3, 2, 1, 2, 2, 8, 1, 224, 229, 181, 131, 103, 163, 224, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 12, 5, 0, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 50, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 30, 23, 13, 49, 52, 48, 52, 51, 48, 49, 56, 49, 48, 48, 57, 90, 23, 13, 51, 57, 48, 52, 51, 48, 49, 56, 49, 48, 48, 57, 90, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 50, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 130, 2, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 2, 15, 0, 48, 130, 2, 10, 2, 130, 2, 1, 0, 216, 17, 18, 72, 72, 218, 41, 138, 73, 197, 28, 199, 236, 110, 51, 109, 254, 77, 251, 224, 28, 222, 172, 94, 226, 54, 167, 36, 249, 127, 80, 107, 76, 206, 185, 48, 84, 39, 229, 179, 214, 237, 37, 230, 48, 182, 5, 55, 94, 20, 34, 17, 197, 232, 170, 27, 210, 251, 178, 210, 9, 149, 56, 164, 239, 42, 73, 140, 93, 62, 113, 102, 3, 56, 251, 22, 245, 133, 136, 228, 90, 146, 12, 4, 50, 242, 200, 64, 251, 82, 95, 159, 246, 192, 241, 227, 186, 69, 160, 80, 213, 18, 139, 242, 221, 222, 145, 134, 35, 240, 245, 182, 114, 46, 1, 218, 11, 246, 46, 57, 8, 95, 25, 161, 99, 65, 11, 28, 167, 148, 193, 134, 196, 83, 47, 118, 246, 10, 215, 12, 209, 131, 63, 26, 83, 25, 243, 87, 213, 39, 127, 252, 19, 184, 248, 146, 141, 252, 211, 40, 67, 60, 181, 104, 0, 37, 93, 39, 98, 211, 221, 85, 221, 68, 32, 144, 131, 53, 147, 197, 191, 184, 25, 251, 107, 227, 220, 8, 66, 230, 175, 109, 250, 158, 64, 202, 78, 133, 133, 120, 73, 177, 215, 195, 193, 48, 57, 50, 171, 126, 95, 170, 211, 139, 111, 159, 45, 26, 33, 104, 112, 103, 179, 163, 241, 152, 65, 109, 145, 124, 248, 215, 219, 168, 231, 95, 33, 26, 140, 51, 191, 49, 116, 183, 184, 209, 244, 224, 34, 244, 191, 114, 52, 223, 247, 129, 77, 113, 125, 81, 161, 226, 179, 240, 211, 40, 22, 115, 111, 205, 204, 173, 55, 125, 78, 235, 173, 64, 225, 63, 129, 253, 247, 61, 10, 62, 162, 241, 189, 49, 150, 41, 89, 220, 194, 25, 128, 140, 91, 116, 198, 44, 211, 16, 83, 38, 29, 20, 79, 196, 212, 129, 102, 60, 135, 103, 51, 39, 20, 8, 233, 180, 119, 132, 52, 82, 143, 137, 248, 104, 152, 23, 191, 195, 187, 170, 19, 147, 31, 93, 84, 47, 168, 199, 124, 251, 13, 20, 190, 21, 61, 36, 52, 242, 154, 220, 117, 65, 102, 34, 180, 1, 214, 11, 175, 144, 158, 12, 234, 98, 248, 155, 89, 60, 8, 226, 150, 52, 228, 99, 222, 188, 55, 212, 235, 12, 136, 3, 67, 11, 80, 175, 160, 52, 221, 80, 77, 21, 251, 90, 36, 216, 12, 250, 12, 99, 158, 31, 3, 177, 225, 238, 225, 170, 67, 244, 102, 101, 40, 55, 2, 49, 239, 1, 199, 30, 209, 204, 159, 109, 202, 84, 58, 64, 219, 206, 207, 79, 70, 139, 74, 101, 154, 106, 198, 104, 108, 215, 204, 153, 27, 71, 176, 114, 195, 119, 143, 196, 247, 97, 156, 116, 31, 206, 253, 107, 161, 194, 156, 148, 130, 171, 148, 162, 231, 189, 27, 186, 185, 112, 57, 149, 23, 197, 41, 243, 57, 88, 52, 245, 196, 164, 198, 123, 96, 185, 102, 67, 80, 63, 110, 97, 252, 14, 249, 134, 170, 96, 12, 67, 75, 149, 2, 3, 1, 0, 1, 163, 66, 48, 64, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 196, 153, 19, 108, 24, 3, 194, 123, 192, 163, 160, 13, 127, 114, 128, 122, 28, 119, 38, 141, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 12, 5, 0, 3, 130, 2, 1, 0, 81, 166, 243, 226, 244, 184, 61, 147, 191, 45, 206, 15, 187, 91, 225, 85, 20, 78, 78, 209, 229, 206, 121, 93, 129, 127, 254, 182, 240, 135, 51, 248, 239, 148, 229, 126, 220, 106, 121, 167, 28, 190, 240, 148, 183, 166, 209, 48, 156, 200, 13, 10, 117, 158, 125, 146, 149, 126, 24, 157, 126, 194, 113, 105, 124, 20, 234, 207, 131, 14, 228, 20, 66, 158, 116, 14, 16, 205, 171, 26, 186, 17, 97, 129, 120, 216, 241, 181, 69, 64, 120, 171, 168, 192, 206, 251, 125, 99, 55, 104, 246, 231, 251, 175, 198, 195, 75, 236, 31, 54, 38, 19, 84, 134, 148, 114, 178, 234, 2, 237, 139, 109, 228, 12, 166, 144, 192, 87, 117, 207, 140, 66, 125, 92, 230, 49, 125, 243, 201, 178, 146, 105, 70, 14, 136, 248, 227, 45, 66, 178, 56, 168, 166, 25, 141, 241, 159, 205, 238, 106, 101, 188, 26, 176, 37, 189, 167, 41, 253, 244, 62, 162, 117, 73, 191, 158, 219, 201, 247, 167, 30, 99, 153, 225, 92, 70, 255, 146, 5, 140, 250, 30, 32, 249, 134, 148, 86, 37, 229, 180, 87, 56, 157, 235, 136, 100, 20, 33, 73, 33, 57, 191, 98, 102, 169, 177, 162, 202, 111, 63, 33, 96, 197, 137, 212, 69, 54, 200, 152, 124, 189, 246, 254, 153, 73, 128, 59, 44, 210, 166, 167, 136, 3, 4, 49, 25, 183, 182, 58, 97, 69, 250, 201, 242, 35, 200, 99, 115, 191, 86, 137, 49, 176, 217, 124, 98, 167, 123, 21, 168, 136, 138, 171, 56, 64, 194, 204, 18, 255, 21, 227, 240, 55, 223, 55, 114, 203, 204, 152, 230, 191, 162, 188, 250, 38, 138, 113, 86, 215, 231, 36, 27, 72, 68, 62, 158, 252, 159, 201, 204, 26, 236, 67, 60, 1, 188, 52, 120, 200, 105, 245, 198, 230, 86, 236, 6, 9, 54, 144, 235, 20, 74, 27, 94, 201, 136, 35, 218, 3, 48, 145, 11, 184, 54, 62, 249, 231, 181, 40, 111, 190, 63, 236, 60, 143, 101, 29, 229, 192, 30, 135, 164, 170, 186, 152, 253, 146, 227, 108, 38, 119, 221, 6, 180, 100, 6, 135, 244, 78, 214, 186, 74, 170, 22, 168, 244, 5, 103, 102, 150, 186, 226, 85, 121, 195, 44, 93, 73, 143, 128, 73, 43, 138, 18, 199, 118, 128, 81, 223, 186, 189, 101, 93, 62, 55, 71, 99, 49, 233, 229, 244, 197, 63, 75, 173, 4, 138, 122, 113, 44, 175, 9, 67, 55, 15, 168, 227, 50, 79, 244, 69, 182, 109, 151, 54, 236, 132, 245, 10, 1, 234, 23, 187, 133, 141, 66, 147, 112, 195, 80, 229, 20, 139, 191, 63, 195, 65, 15, 221, 34, 4, 35, 8, 138, 186, 109, 113, 68, 171, 115, 9, 58, 201, 249, 82, 128, 9, 223, 186, 233, 230, 22, 202, 46, 46, 76, 178, 211, 220, 229, 4, 84, 178, 212, 52, 128, 50, 181, 188, 15, 23, 225] + static let AppleComputerRootCertificate_cer: [UInt8] = [48, 130, 5, 186, 48, 130, 4, 162, 160, 3, 2, 1, 2, 2, 1, 1, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 48, 129, 134, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 29, 48, 27, 6, 3, 85, 4, 10, 19, 20, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 44, 32, 73, 110, 99, 46, 49, 45, 48, 43, 6, 3, 85, 4, 11, 19, 36, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 41, 48, 39, 6, 3, 85, 4, 3, 19, 32, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 48, 30, 23, 13, 48, 53, 48, 50, 49, 48, 48, 48, 49, 56, 49, 52, 90, 23, 13, 50, 53, 48, 50, 49, 48, 48, 48, 49, 56, 49, 52, 90, 48, 129, 134, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 29, 48, 27, 6, 3, 85, 4, 10, 19, 20, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 44, 32, 73, 110, 99, 46, 49, 45, 48, 43, 6, 3, 85, 4, 11, 19, 36, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 41, 48, 39, 6, 3, 85, 4, 3, 19, 32, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 228, 145, 169, 9, 31, 145, 219, 30, 71, 80, 235, 5, 237, 94, 121, 132, 45, 235, 54, 162, 87, 76, 85, 236, 139, 25, 137, 222, 249, 75, 108, 245, 7, 171, 34, 48, 2, 232, 24, 62, 248, 80, 9, 211, 127, 65, 168, 152, 249, 209, 202, 102, 156, 36, 107, 17, 208, 163, 187, 228, 27, 42, 195, 31, 149, 158, 122, 12, 164, 71, 139, 91, 212, 22, 55, 51, 203, 196, 15, 77, 206, 20, 105, 209, 201, 25, 114, 245, 93, 14, 213, 127, 95, 155, 242, 37, 3, 186, 85, 143, 77, 93, 13, 241, 100, 53, 35, 21, 75, 21, 89, 29, 179, 148, 247, 246, 156, 158, 207, 80, 186, 193, 88, 80, 103, 143, 8, 180, 32, 247, 203, 172, 44, 32, 111, 112, 182, 63, 1, 48, 140, 183, 67, 207, 15, 157, 61, 243, 43, 73, 40, 26, 200, 254, 206, 181, 185, 14, 217, 94, 28, 214, 203, 61, 181, 58, 173, 244, 15, 14, 0, 146, 11, 177, 33, 22, 46, 116, 213, 60, 13, 219, 98, 22, 171, 163, 113, 146, 71, 83, 85, 193, 175, 47, 65, 179, 248, 251, 227, 112, 205, 230, 163, 76, 69, 126, 31, 76, 107, 80, 150, 65, 137, 196, 116, 98, 11, 16, 131, 65, 135, 51, 138, 129, 177, 48, 88, 236, 90, 4, 50, 140, 104, 179, 143, 29, 222, 101, 115, 255, 103, 94, 101, 188, 73, 216, 118, 159, 51, 20, 101, 161, 119, 148, 201, 45, 2, 3, 1, 0, 1, 163, 130, 2, 47, 48, 130, 2, 43, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 130, 1, 41, 6, 3, 85, 29, 32, 4, 130, 1, 32, 48, 130, 1, 28, 48, 130, 1, 24, 6, 9, 42, 134, 72, 134, 247, 99, 100, 5, 1, 48, 130, 1, 9, 48, 65, 6, 8, 43, 6, 1, 5, 5, 7, 2, 1, 22, 53, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 97, 117, 116, 104, 111, 114, 105, 116, 121, 47, 116, 101, 114, 109, 115, 46, 104, 116, 109, 108, 48, 129, 195, 6, 8, 43, 6, 1, 5, 5, 7, 2, 2, 48, 129, 182, 26, 129, 179, 82, 101, 108, 105, 97, 110, 99, 101, 32, 111, 110, 32, 116, 104, 105, 115, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 98, 121, 32, 97, 110, 121, 32, 112, 97, 114, 116, 121, 32, 97, 115, 115, 117, 109, 101, 115, 32, 97, 99, 99, 101, 112, 116, 97, 110, 99, 101, 32, 111, 102, 32, 116, 104, 101, 32, 116, 104, 101, 110, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, 115, 116, 97, 110, 100, 97, 114, 100, 32, 116, 101, 114, 109, 115, 32, 97, 110, 100, 32, 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 32, 111, 102, 32, 117, 115, 101, 44, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 112, 111, 108, 105, 99, 121, 32, 97, 110, 100, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 112, 114, 97, 99, 116, 105, 99, 101, 32, 115, 116, 97, 116, 101, 109, 101, 110, 116, 115, 46, 48, 68, 6, 3, 85, 29, 31, 4, 61, 48, 59, 48, 57, 160, 55, 160, 53, 134, 51, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 97, 117, 116, 104, 111, 114, 105, 116, 121, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 85, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 73, 48, 71, 48, 69, 6, 8, 43, 6, 1, 5, 5, 7, 48, 2, 134, 57, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 97, 117, 116, 104, 111, 114, 105, 116, 121, 47, 99, 97, 115, 105, 103, 110, 101, 114, 115, 46, 104, 116, 109, 108, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 3, 130, 1, 1, 0, 157, 218, 45, 40, 88, 47, 125, 118, 4, 185, 4, 211, 62, 206, 183, 102, 99, 78, 143, 47, 212, 254, 75, 173, 114, 189, 163, 57, 198, 82, 77, 5, 152, 82, 245, 137, 81, 1, 36, 121, 190, 26, 50, 247, 229, 68, 139, 75, 68, 7, 57, 130, 214, 90, 202, 180, 32, 94, 217, 174, 21, 93, 29, 140, 29, 50, 191, 56, 49, 98, 72, 93, 199, 225, 144, 177, 248, 36, 64, 248, 95, 88, 155, 81, 93, 87, 157, 193, 229, 255, 60, 204, 114, 33, 110, 196, 233, 233, 161, 119, 215, 44, 23, 38, 195, 63, 235, 154, 232, 11, 3, 186, 233, 179, 74, 114, 235, 51, 9, 91, 173, 230, 98, 49, 106, 232, 175, 47, 213, 175, 30, 87, 118, 143, 127, 55, 45, 46, 2, 92, 221, 99, 201, 242, 113, 184, 38, 64, 223, 21, 141, 117, 68, 63, 121, 189, 230, 29, 153, 225, 67, 44, 62, 173, 111, 190, 185, 164, 254, 14, 53, 25, 81, 99, 177, 195, 222, 181, 146, 62, 81, 120, 1, 115, 138, 164, 35, 202, 164, 136, 241, 30, 92, 31, 65, 22, 45, 126, 149, 10, 170, 233, 137, 65, 152, 27, 26, 221, 203, 32, 191, 71, 94, 12, 38, 197, 85, 53, 77, 198, 48, 139, 153, 103, 20, 199, 9, 31, 186, 71, 199, 218, 1, 9, 135, 36, 66, 149, 189, 19, 96, 25, 10, 239, 234, 127, 14, 110, 205, 193, 68, 67, 58, 74, 213, 227] + static let AppleWWDRCAG7_cer: [UInt8] = [48, 130, 4, 85, 48, 130, 3, 61, 160, 3, 2, 1, 2, 2, 20, 52, 24, 88, 255, 1, 254, 6, 63, 142, 241, 159, 31, 233, 60, 1, 180, 193, 70, 255, 201, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 50, 49, 49, 49, 55, 50, 48, 52, 48, 53, 51, 90, 23, 13, 50, 51, 49, 49, 49, 55, 50, 48, 52, 48, 53, 50, 90, 48, 117, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 55, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 172, 174, 209, 211, 182, 138, 177, 27, 40, 149, 173, 222, 81, 81, 76, 63, 51, 225, 78, 92, 175, 179, 252, 2, 210, 101, 79, 42, 212, 116, 104, 140, 117, 23, 101, 207, 40, 228, 72, 9, 152, 113, 82, 50, 44, 22, 78, 120, 142, 146, 86, 100, 169, 221, 139, 205, 226, 212, 199, 59, 162, 18, 69, 55, 2, 25, 98, 100, 47, 127, 97, 198, 211, 89, 34, 191, 171, 249, 20, 163, 237, 182, 158, 153, 186, 47, 241, 177, 220, 48, 66, 79, 182, 182, 178, 198, 116, 170, 98, 86, 187, 237, 68, 54, 15, 209, 229, 32, 116, 147, 87, 58, 93, 158, 220, 1, 252, 120, 111, 105, 22, 53, 195, 110, 1, 194, 158, 114, 212, 113, 54, 177, 118, 9, 122, 190, 13, 42, 151, 241, 176, 94, 11, 27, 18, 173, 43, 171, 7, 223, 99, 45, 245, 136, 233, 50, 18, 162, 85, 88, 67, 118, 60, 61, 23, 128, 31, 41, 219, 177, 169, 159, 171, 150, 5, 157, 21, 220, 221, 219, 78, 15, 231, 19, 124, 90, 43, 46, 2, 65, 246, 238, 122, 106, 182, 115, 96, 247, 151, 25, 20, 139, 149, 51, 56, 147, 218, 0, 37, 54, 174, 85, 90, 124, 159, 249, 244, 98, 4, 7, 116, 233, 29, 167, 149, 87, 35, 172, 43, 36, 218, 100, 79, 40, 114, 233, 150, 176, 8, 60, 136, 27, 20, 99, 67, 215, 137, 174, 152, 193, 242, 45, 142, 227, 81, 37, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 93, 66, 16, 108, 27, 187, 199, 82, 151, 78, 68, 189, 19, 39, 185, 58, 18, 119, 131, 43, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 3, 130, 1, 1, 0, 82, 163, 8, 41, 19, 101, 183, 181, 31, 230, 52, 3, 237, 246, 24, 119, 188, 61, 202, 39, 181, 112, 236, 236, 108, 51, 75, 246, 153, 37, 148, 7, 158, 33, 51, 3, 106, 245, 125, 10, 46, 43, 223, 8, 169, 130, 222, 74, 127, 225, 231, 11, 75, 5, 184, 39, 152, 73, 221, 193, 12, 134, 215, 129, 100, 174, 130, 156, 196, 69, 241, 234, 143, 28, 34, 48, 227, 162, 37, 97, 68, 137, 254, 133, 122, 86, 240, 114, 146, 124, 12, 68, 84, 36, 183, 181, 164, 159, 38, 240, 50, 249, 87, 157, 106, 121, 108, 64, 237, 15, 52, 6, 6, 66, 255, 216, 14, 49, 101, 109, 230, 46, 1, 217, 6, 191, 197, 202, 13, 174, 71, 212, 5, 23, 136, 60, 233, 156, 228, 25, 100, 109, 138, 148, 173, 17, 220, 1, 246, 229, 120, 175, 173, 232, 112, 215, 13, 93, 129, 62, 70, 42, 44, 174, 36, 161, 199, 210, 224, 125, 191, 29, 245, 54, 107, 197, 222, 169, 10, 154, 128, 177, 17, 94, 178, 100, 126, 179, 193, 87, 204, 194, 108, 89, 153, 183, 244, 176, 221, 49, 218, 72, 214, 106, 129, 238, 178, 139, 80, 53, 22, 230, 231, 92, 113, 98, 110, 176, 242, 81, 226, 168, 109, 248, 42, 203, 104, 115, 198, 166, 196, 26, 67, 73, 1, 62, 169, 169, 0, 138, 134, 108, 131, 136, 210, 92, 112, 87, 122, 218, 248, 118, 204, 25, 213, 176] + static let AppleIncRootCertificate_cer: [UInt8] = [48, 130, 4, 187, 48, 130, 3, 163, 160, 3, 2, 1, 2, 2, 1, 2, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 48, 54, 48, 52, 50, 53, 50, 49, 52, 48, 51, 54, 90, 23, 13, 51, 53, 48, 50, 48, 57, 50, 49, 52, 48, 51, 54, 90, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 228, 145, 169, 9, 31, 145, 219, 30, 71, 80, 235, 5, 237, 94, 121, 132, 45, 235, 54, 162, 87, 76, 85, 236, 139, 25, 137, 222, 249, 75, 108, 245, 7, 171, 34, 48, 2, 232, 24, 62, 248, 80, 9, 211, 127, 65, 168, 152, 249, 209, 202, 102, 156, 36, 107, 17, 208, 163, 187, 228, 27, 42, 195, 31, 149, 158, 122, 12, 164, 71, 139, 91, 212, 22, 55, 51, 203, 196, 15, 77, 206, 20, 105, 209, 201, 25, 114, 245, 93, 14, 213, 127, 95, 155, 242, 37, 3, 186, 85, 143, 77, 93, 13, 241, 100, 53, 35, 21, 75, 21, 89, 29, 179, 148, 247, 246, 156, 158, 207, 80, 186, 193, 88, 80, 103, 143, 8, 180, 32, 247, 203, 172, 44, 32, 111, 112, 182, 63, 1, 48, 140, 183, 67, 207, 15, 157, 61, 243, 43, 73, 40, 26, 200, 254, 206, 181, 185, 14, 217, 94, 28, 214, 203, 61, 181, 58, 173, 244, 15, 14, 0, 146, 11, 177, 33, 22, 46, 116, 213, 60, 13, 219, 98, 22, 171, 163, 113, 146, 71, 83, 85, 193, 175, 47, 65, 179, 248, 251, 227, 112, 205, 230, 163, 76, 69, 126, 31, 76, 107, 80, 150, 65, 137, 196, 116, 98, 11, 16, 131, 65, 135, 51, 138, 129, 177, 48, 88, 236, 90, 4, 50, 140, 104, 179, 143, 29, 222, 101, 115, 255, 103, 94, 101, 188, 73, 216, 118, 159, 51, 20, 101, 161, 119, 148, 201, 45, 2, 3, 1, 0, 1, 163, 130, 1, 122, 48, 130, 1, 118, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 130, 1, 17, 6, 3, 85, 29, 32, 4, 130, 1, 8, 48, 130, 1, 4, 48, 130, 1, 0, 6, 9, 42, 134, 72, 134, 247, 99, 100, 5, 1, 48, 129, 242, 48, 42, 6, 8, 43, 6, 1, 5, 5, 7, 2, 1, 22, 30, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 97, 112, 112, 108, 101, 99, 97, 47, 48, 129, 195, 6, 8, 43, 6, 1, 5, 5, 7, 2, 2, 48, 129, 182, 26, 129, 179, 82, 101, 108, 105, 97, 110, 99, 101, 32, 111, 110, 32, 116, 104, 105, 115, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 98, 121, 32, 97, 110, 121, 32, 112, 97, 114, 116, 121, 32, 97, 115, 115, 117, 109, 101, 115, 32, 97, 99, 99, 101, 112, 116, 97, 110, 99, 101, 32, 111, 102, 32, 116, 104, 101, 32, 116, 104, 101, 110, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, 115, 116, 97, 110, 100, 97, 114, 100, 32, 116, 101, 114, 109, 115, 32, 97, 110, 100, 32, 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 32, 111, 102, 32, 117, 115, 101, 44, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 112, 111, 108, 105, 99, 121, 32, 97, 110, 100, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 112, 114, 97, 99, 116, 105, 99, 101, 32, 115, 116, 97, 116, 101, 109, 101, 110, 116, 115, 46, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 3, 130, 1, 1, 0, 92, 54, 153, 76, 45, 120, 183, 237, 140, 155, 220, 243, 119, 155, 242, 118, 210, 119, 48, 79, 193, 31, 133, 131, 133, 27, 153, 61, 71, 55, 242, 169, 155, 64, 142, 44, 212, 177, 144, 18, 216, 190, 244, 115, 155, 238, 210, 100, 15, 203, 121, 79, 52, 216, 162, 62, 249, 120, 255, 107, 200, 7, 236, 125, 57, 131, 139, 83, 32, 211, 56, 196, 177, 191, 154, 79, 10, 107, 255, 43, 252, 89, 167, 5, 9, 124, 23, 64, 86, 17, 30, 116, 211, 183, 139, 35, 59, 71, 163, 213, 111, 36, 226, 235, 209, 183, 112, 223, 15, 69, 225, 39, 202, 241, 109, 120, 237, 231, 181, 23, 23, 168, 220, 126, 34, 53, 202, 37, 213, 217, 15, 214, 107, 212, 162, 36, 35, 17, 247, 161, 172, 143, 115, 129, 96, 198, 27, 91, 9, 47, 146, 178, 248, 68, 72, 240, 96, 56, 158, 21, 245, 61, 38, 103, 32, 138, 51, 106, 247, 13, 130, 207, 222, 235, 163, 47, 249, 83, 106, 91, 100, 192, 99, 51, 119, 247, 58, 7, 44, 86, 235, 218, 15, 33, 14, 218, 186, 115, 25, 79, 181, 217, 54, 127, 193, 135, 85, 217, 167, 153, 185, 50, 66, 251, 216, 213, 113, 158, 126, 161, 82, 183, 27, 189, 147, 66, 36, 18, 42, 199, 15, 29, 182, 77, 156, 94, 99, 200, 75, 128, 23, 80, 170, 138, 213, 218, 228, 252, 208, 9, 7, 55, 176, 117, 117, 33] + static let AppleWWDRCAG4_cer: [UInt8] = [48, 130, 4, 85, 48, 130, 3, 61, 160, 3, 2, 1, 2, 2, 20, 19, 220, 119, 149, 82, 113, 229, 61, 198, 50, 232, 204, 255, 229, 33, 243, 204, 197, 206, 210, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 48, 49, 50, 49, 54, 49, 57, 51, 54, 48, 52, 90, 23, 13, 51, 48, 49, 50, 49, 48, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 52, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 208, 31, 120, 170, 122, 39, 50, 176, 70, 95, 231, 23, 118, 216, 160, 157, 14, 41, 142, 173, 61, 50, 165, 196, 107, 55, 201, 228, 65, 145, 106, 183, 121, 113, 93, 12, 52, 4, 96, 117, 247, 174, 67, 143, 71, 196, 134, 30, 8, 232, 191, 214, 57, 82, 47, 30, 103, 252, 113, 241, 130, 109, 60, 126, 6, 82, 118, 157, 44, 188, 213, 67, 233, 177, 180, 188, 64, 58, 120, 81, 93, 81, 161, 37, 225, 190, 108, 145, 157, 107, 33, 89, 24, 65, 213, 15, 141, 109, 65, 42, 57, 74, 33, 224, 144, 159, 78, 19, 79, 208, 140, 154, 50, 184, 215, 106, 146, 30, 37, 106, 164, 50, 206, 34, 25, 133, 5, 96, 220, 2, 74, 242, 90, 235, 119, 121, 2, 125, 192, 151, 84, 108, 146, 142, 118, 1, 230, 70, 143, 229, 230, 42, 251, 162, 176, 173, 24, 173, 109, 51, 133, 56, 35, 139, 234, 138, 150, 237, 159, 174, 102, 79, 163, 12, 64, 39, 109, 149, 208, 98, 136, 217, 67, 41, 39, 253, 237, 164, 191, 83, 46, 144, 21, 101, 60, 217, 46, 98, 100, 51, 29, 108, 106, 221, 142, 33, 170, 164, 95, 21, 198, 48, 237, 95, 230, 140, 54, 146, 148, 183, 220, 57, 2, 0, 251, 100, 140, 212, 12, 129, 242, 63, 213, 52, 151, 135, 117, 38, 194, 111, 174, 3, 99, 33, 12, 123, 212, 27, 177, 98, 197, 2, 156, 189, 253, 175, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 91, 217, 250, 29, 231, 154, 26, 11, 163, 153, 118, 34, 80, 134, 62, 145, 200, 91, 119, 168, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, 63, 86, 61, 158, 229, 182, 195, 121, 230, 69, 32, 104, 189, 191, 115, 139, 44, 18, 158, 2, 227, 174, 128, 34, 140, 4, 30, 195, 82, 200, 112, 128, 168, 251, 206, 167, 176, 213, 66, 68, 130, 3, 130, 79, 6, 252, 59, 73, 20, 251, 216, 116, 82, 133, 175, 167, 157, 33, 231, 1, 18, 3, 159, 205, 64, 88, 208, 1, 215, 191, 50, 131, 43, 83, 88, 40, 60, 238, 156, 159, 84, 118, 61, 100, 39, 198, 126, 141, 29, 56, 77, 45, 174, 129, 230, 185, 165, 184, 156, 137, 148, 247, 159, 199, 135, 165, 81, 102, 52, 27, 57, 113, 57, 36, 227, 135, 103, 239, 165, 177, 104, 123, 140, 238, 61, 247, 174, 182, 123, 226, 210, 255, 223, 97, 198, 106, 117, 73, 149, 34, 68, 168, 4, 252, 148, 184, 11, 46, 57, 17, 73, 18, 209, 229, 129, 234, 89, 0, 79, 91, 60, 90, 54, 218, 122, 34, 115, 9, 9, 105, 205, 192, 124, 234, 226, 36, 254, 152, 68, 184, 248, 239, 178, 113, 63, 26, 93, 212, 93, 126, 51, 77, 156, 29, 36, 190, 0, 240, 144, 3, 88, 153, 65, 61, 49, 90, 98, 64, 175, 57, 168, 81, 67, 146, 171, 4, 168, 156, 194, 77, 177, 75, 210, 171, 124, 74, 95, 235, 157, 59, 188, 79, 136, 64, 6, 19, 255, 144, 23, 138, 8, 71, 41, 232, 98, 152, 41, 165, 79, 17, 5, 105, 58, 207, 242, 159] + static let AppleWWDRCAG6_cer: [UInt8] = [48, 130, 3, 22, 48, 130, 2, 156, 160, 3, 2, 1, 2, 2, 20, 34, 193, 161, 71, 10, 116, 115, 105, 239, 83, 134, 18, 201, 198, 159, 61, 56, 243, 108, 215, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 30, 23, 13, 50, 49, 48, 51, 49, 55, 50, 48, 51, 55, 49, 48, 90, 23, 13, 51, 54, 48, 51, 49, 57, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 54, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 118, 48, 16, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 5, 43, 129, 4, 0, 34, 3, 98, 0, 4, 110, 196, 10, 11, 222, 15, 174, 85, 166, 101, 121, 215, 130, 220, 115, 117, 82, 75, 241, 61, 18, 25, 137, 224, 13, 17, 169, 158, 9, 247, 55, 163, 211, 240, 147, 4, 111, 177, 67, 139, 134, 193, 152, 248, 66, 157, 157, 255, 178, 174, 143, 23, 247, 6, 112, 165, 214, 176, 190, 111, 58, 215, 145, 135, 34, 120, 231, 29, 192, 72, 254, 220, 56, 31, 154, 106, 143, 116, 125, 202, 113, 74, 255, 196, 100, 86, 231, 136, 6, 205, 129, 145, 161, 34, 26, 72, 163, 129, 250, 48, 129, 247, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 187, 176, 222, 161, 88, 51, 136, 154, 164, 138, 153, 222, 190, 189, 235, 175, 218, 203, 36, 171, 48, 70, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 58, 48, 56, 48, 54, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 42, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 103, 51, 48, 55, 6, 3, 85, 29, 31, 4, 48, 48, 46, 48, 44, 160, 42, 160, 40, 134, 38, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 103, 51, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 63, 47, 148, 35, 81, 211, 80, 201, 154, 40, 61, 237, 176, 124, 229, 207, 165, 144, 98, 153, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, 3, 104, 0, 48, 101, 2, 48, 64, 94, 20, 170, 228, 140, 138, 162, 3, 2, 62, 220, 56, 247, 64, 90, 7, 174, 251, 9, 161, 6, 37, 123, 159, 64, 31, 196, 169, 145, 157, 232, 36, 163, 136, 43, 78, 158, 227, 19, 109, 117, 87, 155, 28, 92, 197, 249, 2, 49, 0, 211, 72, 252, 90, 173, 149, 239, 54, 185, 49, 83, 116, 228, 80, 194, 55, 223, 44, 239, 21, 85, 81, 79, 140, 49, 88, 144, 189, 247, 131, 172, 117, 198, 120, 249, 17, 141, 177, 128, 242, 71, 152, 38, 118, 189, 39, 12, 104] + static let AppleWWDRCAG8_cer: [UInt8] = [48, 130, 4, 85, 48, 130, 3, 61, 160, 3, 2, 1, 2, 2, 20, 84, 181, 11, 175, 121, 13, 141, 127, 140, 175, 104, 76, 86, 47, 80, 105, 10, 26, 186, 95, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 51, 48, 54, 50, 48, 50, 51, 51, 55, 49, 53, 90, 23, 13, 50, 53, 48, 49, 50, 52, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 56, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 208, 64, 16, 212, 8, 249, 82, 33, 99, 79, 60, 104, 247, 212, 156, 130, 2, 140, 131, 104, 188, 183, 141, 127, 136, 231, 66, 77, 44, 239, 34, 165, 194, 137, 222, 189, 12, 215, 77, 97, 80, 45, 57, 228, 48, 115, 165, 210, 213, 104, 154, 51, 242, 239, 217, 42, 173, 46, 31, 3, 186, 248, 165, 241, 66, 11, 87, 46, 70, 198, 208, 88, 211, 112, 95, 247, 178, 55, 239, 106, 31, 62, 191, 137, 57, 194, 173, 254, 245, 5, 251, 88, 150, 49, 200, 135, 44, 213, 35, 186, 117, 176, 44, 245, 171, 160, 186, 242, 32, 12, 76, 235, 36, 99, 105, 233, 34, 64, 240, 142, 88, 91, 222, 100, 123, 137, 27, 81, 18, 4, 224, 23, 178, 89, 205, 223, 241, 231, 206, 175, 44, 50, 232, 105, 193, 208, 8, 126, 29, 162, 71, 115, 209, 75, 59, 253, 185, 133, 220, 71, 167, 40, 130, 121, 41, 72, 137, 2, 40, 226, 193, 236, 44, 31, 91, 134, 252, 216, 182, 203, 113, 192, 115, 1, 75, 252, 5, 17, 17, 108, 1, 3, 52, 90, 246, 129, 194, 94, 31, 124, 20, 14, 222, 63, 107, 33, 203, 79, 245, 215, 97, 230, 132, 3, 146, 188, 231, 37, 41, 158, 205, 91, 12, 193, 219, 227, 196, 58, 217, 118, 87, 172, 47, 56, 20, 25, 200, 183, 177, 162, 85, 79, 95, 78, 142, 25, 89, 169, 218, 253, 114, 218, 176, 4, 33, 5, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 181, 189, 188, 128, 196, 12, 227, 56, 164, 244, 183, 173, 35, 179, 239, 68, 206, 185, 90, 133, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 3, 130, 1, 1, 0, 76, 179, 235, 122, 57, 148, 74, 149, 102, 250, 22, 49, 234, 13, 138, 143, 93, 66, 56, 198, 7, 205, 232, 201, 34, 172, 252, 8, 66, 126, 95, 147, 95, 49, 42, 168, 34, 193, 118, 25, 43, 238, 174, 114, 233, 189, 86, 207, 73, 36, 146, 8, 247, 205, 25, 117, 195, 249, 26, 39, 13, 14, 220, 41, 141, 63, 182, 219, 165, 79, 76, 114, 196, 96, 145, 137, 17, 126, 36, 149, 67, 34, 96, 103, 188, 223, 255, 171, 229, 60, 22, 23, 157, 130, 20, 78, 157, 244, 117, 254, 80, 185, 173, 5, 178, 184, 121, 246, 149, 214, 16, 229, 246, 83, 244, 207, 35, 230, 119, 15, 236, 184, 75, 105, 248, 226, 158, 2, 49, 217, 142, 217, 202, 190, 99, 94, 95, 225, 160, 105, 206, 193, 205, 110, 73, 163, 120, 97, 175, 57, 60, 106, 75, 10, 52, 37, 100, 213, 48, 181, 60, 171, 221, 17, 129, 57, 113, 232, 192, 195, 88, 128, 17, 16, 26, 17, 210, 194, 188, 89, 240, 138, 217, 53, 115, 192, 230, 109, 228, 201, 125, 98, 20, 62, 130, 2, 169, 16, 105, 55, 121, 97, 111, 240, 70, 148, 62, 53, 245, 171, 172, 99, 208, 216, 94, 89, 87, 105, 209, 184, 75, 110, 93, 212, 95, 19, 156, 112, 78, 37, 17, 220, 36, 44, 30, 22, 158, 150, 90, 4, 237, 69, 238, 58, 238, 103, 93, 143, 195, 134, 176, 245, 76, 31, 104, 16] + static let AppleRootCA_G3_cer: [UInt8] = [48, 130, 2, 67, 48, 130, 1, 201, 160, 3, 2, 1, 2, 2, 8, 45, 197, 252, 136, 210, 197, 75, 149, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 30, 23, 13, 49, 52, 48, 52, 51, 48, 49, 56, 49, 57, 48, 54, 90, 23, 13, 51, 57, 48, 52, 51, 48, 49, 56, 49, 57, 48, 54, 90, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 118, 48, 16, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 5, 43, 129, 4, 0, 34, 3, 98, 0, 4, 152, 233, 47, 61, 64, 114, 164, 237, 147, 34, 114, 129, 19, 28, 221, 16, 149, 241, 197, 163, 78, 113, 220, 20, 22, 217, 14, 229, 166, 5, 42, 119, 100, 123, 95, 78, 56, 211, 187, 28, 68, 181, 127, 245, 31, 182, 50, 98, 93, 201, 233, 132, 91, 79, 48, 79, 17, 90, 0, 253, 88, 88, 12, 165, 245, 15, 44, 77, 7, 71, 19, 117, 218, 151, 151, 151, 111, 49, 92, 237, 43, 157, 123, 32, 59, 216, 185, 84, 217, 94, 153, 164, 58, 81, 10, 49, 163, 66, 48, 64, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 187, 176, 222, 161, 88, 51, 136, 154, 164, 138, 153, 222, 190, 189, 235, 175, 218, 203, 36, 171, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, 3, 104, 0, 48, 101, 2, 49, 0, 131, 233, 193, 196, 22, 94, 26, 93, 52, 24, 217, 237, 239, 244, 108, 14, 0, 70, 75, 184, 223, 178, 70, 17, 197, 15, 253, 230, 122, 140, 161, 166, 107, 206, 194, 3, 212, 156, 245, 147, 198, 116, 184, 106, 223, 170, 35, 21, 2, 48, 109, 102, 138, 16, 202, 212, 13, 212, 79, 205, 141, 67, 62, 180, 138, 99, 165, 51, 110, 227, 109, 218, 23, 183, 100, 31, 200, 83, 38, 249, 136, 98, 116, 57, 11, 23, 91, 203, 81, 168, 12, 232, 24, 3, 231, 162, 178, 40] +} diff --git a/Sources/QueryEngine/CacheKey.swift b/Sources/QueryEngine/CacheKey.swift index b10bac987d3..c98f3c963f9 100644 --- a/Sources/QueryEngine/CacheKey.swift +++ b/Sources/QueryEngine/CacheKey.swift @@ -20,154 +20,154 @@ public protocol CacheKey: Encodable {} /// Types that cannot be decomposed more to be hashed protocol LeafCacheKey: CacheKey { - func hash(with hashFunction: inout some HashFunction) + func hash(with hashFunction: inout some HashFunction) } extension Bool: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - hashFunction.update(data: self ? [1] : [0]) - } + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + hashFunction.update(data: self ? [1] : [0]) + } } extension Int: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension Int8: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension Int16: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension Int32: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension Int64: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension UInt: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension UInt8: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension UInt16: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension UInt32: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension UInt64: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension Float: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension Double: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - withUnsafeBytes(of: self) { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + withUnsafeBytes(of: self) { + hashFunction.update(data: $0) + } } - } } extension String: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - var t = String(reflecting: Self.self) - t.withUTF8 { - hashFunction.update(data: $0) - } - var x = self - x.withUTF8 { - hashFunction.update(data: $0) + func hash(with hashFunction: inout some HashFunction) { + var t = String(reflecting: Self.self) + t.withUTF8 { + hashFunction.update(data: $0) + } + var x = self + x.withUTF8 { + hashFunction.update(data: $0) + } } - } } extension FilePath: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - self.string.hash(with: &hashFunction) - } + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + self.string.hash(with: &hashFunction) + } } extension FilePath.Component: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - self.string.hash(with: &hashFunction) - } + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + self.string.hash(with: &hashFunction) + } } extension URL: LeafCacheKey { - func hash(with hashFunction: inout some HashFunction) { - String(reflecting: Self.self).hash(with: &hashFunction) - self.description.hash(with: &hashFunction) - } + func hash(with hashFunction: inout some HashFunction) { + String(reflecting: Self.self).hash(with: &hashFunction) + self.description.hash(with: &hashFunction) + } } diff --git a/Sources/Runtimes/CompilerPluginSupport/TargetExtensions.swift b/Sources/Runtimes/CompilerPluginSupport/TargetExtensions.swift index b3c6f679d35..58ae6034fac 100644 --- a/Sources/Runtimes/CompilerPluginSupport/TargetExtensions.swift +++ b/Sources/Runtimes/CompilerPluginSupport/TargetExtensions.swift @@ -25,16 +25,18 @@ public extension Target { linkerSettings: [LinkerSetting]? = nil, plugins: [PluginUsage]? = nil ) -> Target { - return Target(name: name, - dependencies: dependencies, - path: path, - exclude: exclude, - sources: sources, - publicHeadersPath: nil, - type: .macro, - packageAccess: packageAccess, - swiftSettings: swiftSettings, - linkerSettings: linkerSettings, - plugins: plugins) + return Target( + name: name, + dependencies: dependencies, + path: path, + exclude: exclude, + sources: sources, + publicHeadersPath: nil, + type: .macro, + packageAccess: packageAccess, + swiftSettings: swiftSettings, + linkerSettings: linkerSettings, + plugins: plugins + ) } } diff --git a/Sources/Runtimes/PackageDescription/BuildSettings.swift b/Sources/Runtimes/PackageDescription/BuildSettings.swift index 0f4074dbef5..32b9647926b 100644 --- a/Sources/Runtimes/PackageDescription/BuildSettings.swift +++ b/Sources/Runtimes/PackageDescription/BuildSettings.swift @@ -203,7 +203,7 @@ public struct CSetting: Sendable { public static func unsafeFlags(_ flags: [String], _ condition: BuildSettingCondition? = nil) -> CSetting { return CSetting(name: "unsafeFlags", value: flags, condition: condition) } - + /// Controls how all C compiler warnings are treated during compilation. /// /// Use this setting to specify whether all warnings should be treated as warnings (default behavior) @@ -220,11 +220,14 @@ public struct CSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func treatAllWarnings( - as level: WarningLevel, - _ condition: BuildSettingCondition? = nil + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil ) -> CSetting { return CSetting( - name: "treatAllWarnings", value: [level.rawValue], condition: condition) + name: "treatAllWarnings", + value: [level.rawValue], + condition: condition + ) } /// Controls how a specific C compiler warning is treated during compilation. @@ -244,12 +247,15 @@ public struct CSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func treatWarning( - _ name: String, - as level: WarningLevel, - _ condition: BuildSettingCondition? = nil + _ name: String, + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil ) -> CSetting { return CSetting( - name: "treatWarning", value: [name, level.rawValue], condition: condition) + name: "treatWarning", + value: [name, level.rawValue], + condition: condition + ) } /// Enable a specific C compiler warning group. @@ -264,11 +270,14 @@ public struct CSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func enableWarning( - _ name: String, - _ condition: BuildSettingCondition? = nil + _ name: String, + _ condition: BuildSettingCondition? = nil ) -> CSetting { return CSetting( - name: "enableWarning", value: [name], condition: condition) + name: "enableWarning", + value: [name], + condition: condition + ) } /// Disable a specific C compiler warning group. @@ -283,11 +292,14 @@ public struct CSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func disableWarning( - _ name: String, - _ condition: BuildSettingCondition? = nil + _ name: String, + _ condition: BuildSettingCondition? = nil ) -> CSetting { return CSetting( - name: "disableWarning", value: [name], condition: condition) + name: "disableWarning", + value: [name], + condition: condition + ) } } @@ -359,7 +371,7 @@ public struct CXXSetting: Sendable { public static func unsafeFlags(_ flags: [String], _ condition: BuildSettingCondition? = nil) -> CXXSetting { return CXXSetting(name: "unsafeFlags", value: flags, condition: condition) } - + /// Controls how all C++ compiler warnings are treated during compilation. /// /// Use this setting to specify whether all warnings should be treated as warnings (default behavior) @@ -376,11 +388,14 @@ public struct CXXSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func treatAllWarnings( - as level: WarningLevel, - _ condition: BuildSettingCondition? = nil + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil ) -> CXXSetting { return CXXSetting( - name: "treatAllWarnings", value: [level.rawValue], condition: condition) + name: "treatAllWarnings", + value: [level.rawValue], + condition: condition + ) } /// Controls how a specific C++ compiler warning is treated during compilation. @@ -400,12 +415,15 @@ public struct CXXSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func treatWarning( - _ name: String, - as level: WarningLevel, - _ condition: BuildSettingCondition? = nil + _ name: String, + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil ) -> CXXSetting { return CXXSetting( - name: "treatWarning", value: [name, level.rawValue], condition: condition) + name: "treatWarning", + value: [name, level.rawValue], + condition: condition + ) } /// Enable a specific C++ compiler warning group. @@ -420,11 +438,14 @@ public struct CXXSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func enableWarning( - _ name: String, - _ condition: BuildSettingCondition? = nil + _ name: String, + _ condition: BuildSettingCondition? = nil ) -> CXXSetting { return CXXSetting( - name: "enableWarning", value: [name], condition: condition) + name: "enableWarning", + value: [name], + condition: condition + ) } /// Disable a specific C++ compiler warning group. @@ -439,11 +460,14 @@ public struct CXXSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func disableWarning( - _ name: String, - _ condition: BuildSettingCondition? = nil + _ name: String, + _ condition: BuildSettingCondition? = nil ) -> CXXSetting { return CXXSetting( - name: "disableWarning", value: [name], condition: condition) + name: "disableWarning", + value: [name], + condition: condition + ) } } @@ -526,7 +550,10 @@ public struct SwiftSetting: Sendable { _ condition: BuildSettingCondition? = nil ) -> SwiftSetting { return SwiftSetting( - name: "enableUpcomingFeature", value: [name], condition: condition) + name: "enableUpcomingFeature", + value: [name], + condition: condition + ) } /// Enable an experimental feature with the given name. @@ -550,7 +577,10 @@ public struct SwiftSetting: Sendable { _ condition: BuildSettingCondition? = nil ) -> SwiftSetting { return SwiftSetting( - name: "enableExperimentalFeature", value: [name], condition: condition) + name: "enableExperimentalFeature", + value: [name], + condition: condition + ) } /// Enable strict memory safety checking. @@ -569,10 +599,13 @@ public struct SwiftSetting: Sendable { /// setting. @available(_PackageDescription, introduced: 6.2) public static func strictMemorySafety( - _ condition: BuildSettingCondition? = nil + _ condition: BuildSettingCondition? = nil ) -> SwiftSetting { return SwiftSetting( - name: "strictMemorySafety", value: ["ON"], condition: condition) + name: "strictMemorySafety", + value: ["ON"], + condition: condition + ) } /// The interoperability mode @@ -599,11 +632,14 @@ public struct SwiftSetting: Sendable { /// setting. @available(_PackageDescription, introduced: 5.9) public static func interoperabilityMode( - _ mode: InteroperabilityMode, - _ condition: BuildSettingCondition? = nil + _ mode: InteroperabilityMode, + _ condition: BuildSettingCondition? = nil ) -> SwiftSetting { return SwiftSetting( - name: "interoperabilityMode", value: [mode.rawValue], condition: condition) + name: "interoperabilityMode", + value: [mode.rawValue], + condition: condition + ) } /// Defines a `-swift-version` to pass to the @@ -616,11 +652,14 @@ public struct SwiftSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.0, deprecated: 6.0, renamed: "swiftLanguageMode(_:_:)") public static func swiftLanguageVersion( - _ version: SwiftVersion, - _ condition: BuildSettingCondition? = nil + _ version: SwiftVersion, + _ condition: BuildSettingCondition? = nil ) -> SwiftSetting { return SwiftSetting( - name: "swiftLanguageMode", value: [.init(describing: version)], condition: condition) + name: "swiftLanguageMode", + value: [.init(describing: version)], + condition: condition + ) } /// Defines a `-language-mode` to pass to the @@ -633,11 +672,14 @@ public struct SwiftSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.0) public static func swiftLanguageMode( - _ mode: SwiftLanguageMode, - _ condition: BuildSettingCondition? = nil + _ mode: SwiftLanguageMode, + _ condition: BuildSettingCondition? = nil ) -> SwiftSetting { return SwiftSetting( - name: "swiftLanguageMode", value: [.init(describing: mode)], condition: condition) + name: "swiftLanguageMode", + value: [.init(describing: mode)], + condition: condition + ) } /// Controls how all Swift compiler warnings are treated during compilation. @@ -656,11 +698,14 @@ public struct SwiftSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func treatAllWarnings( - as level: WarningLevel, - _ condition: BuildSettingCondition? = nil + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil ) -> SwiftSetting { return SwiftSetting( - name: "treatAllWarnings", value: [level.rawValue], condition: condition) + name: "treatAllWarnings", + value: [level.rawValue], + condition: condition + ) } /// Controls how a specific Swift compiler warning is treated during compilation. @@ -680,12 +725,15 @@ public struct SwiftSetting: Sendable { /// - condition: A condition that restricts the application of the build setting. @available(_PackageDescription, introduced: 6.2) public static func treatWarning( - _ name: String, - as level: WarningLevel, - _ condition: BuildSettingCondition? = nil + _ name: String, + as level: WarningLevel, + _ condition: BuildSettingCondition? = nil ) -> SwiftSetting { return SwiftSetting( - name: "treatWarning", value: [name, level.rawValue], condition: condition) + name: "treatWarning", + value: [name, level.rawValue], + condition: condition + ) } /// Set the default isolation to the given global actor type. @@ -712,7 +760,10 @@ public struct SwiftSetting: Sendable { "MainActor" } return SwiftSetting( - name: "defaultIsolation", value: [isolationString], condition: condition) + name: "defaultIsolation", + value: [isolationString], + condition: condition + ) } } @@ -756,7 +807,7 @@ public struct LinkerSetting: Sendable { public static func linkedFramework(_ framework: String, _ condition: BuildSettingCondition? = nil) -> LinkerSetting { return LinkerSetting(name: "linkedFramework", value: [framework], condition: condition) } - + /// Sets unsafe flags to pass arbitrary command-line flags to the /// corresponding build tool. /// diff --git a/Sources/Runtimes/PackageDescription/Context.swift b/Sources/Runtimes/PackageDescription/Context.swift index ec0449c9ccf..bbdde9a5be6 100644 --- a/Sources/Runtimes/PackageDescription/Context.swift +++ b/Sources/Runtimes/PackageDescription/Context.swift @@ -19,7 +19,7 @@ public struct Context: Sendable { private static let model = try! ContextModel.decode() /// The directory that contains `Package.swift`. - public static var packageDirectory : String { + public static var packageDirectory: String { model.packageDirectory } @@ -36,10 +36,10 @@ public struct Context: Sendable { } /// Snapshot of the system environment variables. - public static var environment : [String : String] { + public static var environment: [String: String] { model.environment } - + private init() { } } diff --git a/Sources/Runtimes/PackageDescription/LanguageStandardSettings.swift b/Sources/Runtimes/PackageDescription/LanguageStandardSettings.swift index 0ed20357cab..5c8264e2069 100644 --- a/Sources/Runtimes/PackageDescription/LanguageStandardSettings.swift +++ b/Sources/Runtimes/PackageDescription/LanguageStandardSettings.swift @@ -190,5 +190,5 @@ extension SwiftLanguageMode: CustomStringConvertible { } /// Type alias to previous name for backward source compatibility -@available(_PackageDescription, deprecated: 6, renamed:"SwiftLanguageMode") +@available(_PackageDescription, deprecated: 6, renamed: "SwiftLanguageMode") public typealias SwiftVersion = SwiftLanguageMode diff --git a/Sources/Runtimes/PackageDescription/PackageDependency.swift b/Sources/Runtimes/PackageDescription/PackageDependency.swift index 06cf9912343..0a223aee17c 100644 --- a/Sources/Runtimes/PackageDescription/PackageDependency.swift +++ b/Sources/Runtimes/PackageDescription/PackageDependency.swift @@ -11,9 +11,9 @@ //===----------------------------------------------------------------------===// #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import Foundation + @_implementationOnly import Foundation #else -import Foundation + import Foundation #endif extension Package { @@ -165,7 +165,7 @@ extension Package { traits: traits ) } - + convenience init( name: String?, location: String, @@ -181,7 +181,7 @@ extension Package { traits: traits ) } - + convenience init( id: String, requirement: RegistryRequirement, @@ -702,10 +702,13 @@ extension Package.Dependency { // Increase upperbound's patch version by one. let upper = closedRange.upperBound let upperBound = Version( - upper.major, upper.minor, upper.patch + 1, + upper.major, + upper.minor, + upper.patch + 1, prereleaseIdentifiers: upper.prereleaseIdentifiers, - buildMetadataIdentifiers: upper.buildMetadataIdentifiers) - return .package(name: name, url: url, requirement: .range(closedRange.lowerBound ..< upperBound)) + buildMetadataIdentifiers: upper.buildMetadataIdentifiers + ) + return .package(name: name, url: url, requirement: .range(closedRange.lowerBound.. String { var errors: [String] = [] #if os(Windows) -private var dumpInfo: (package: Package, handle: Int)? -private func dumpPackageAtExit(_ package: Package, to handle: Int) { - let dump: @convention(c) () -> Void = { - guard let dumpInfo else { return } - - let hFile: HANDLE = HANDLE(bitPattern: dumpInfo.handle)! - // NOTE: `_open_osfhandle` transfers ownership of the `HANDLE` to the file - // descriptor. DO NOT invoke `CloseHandle` on `hFile`. - let fd: CInt = _open_osfhandle(Int(bitPattern: hFile), _O_APPEND) - // NOTE: `_fdopen` transfers ownership of the file descriptor to the - // `FILE *`. DO NOT invoke `_close` on the `fd`. - guard let fp = _fdopen(fd, "w") else { - _close(fd) - return + private var dumpInfo: (package: Package, handle: Int)? + private func dumpPackageAtExit(_ package: Package, to handle: Int) { + let dump: @convention(c) () -> Void = { + guard let dumpInfo else { return } + + let hFile: HANDLE = HANDLE(bitPattern: dumpInfo.handle)! + // NOTE: `_open_osfhandle` transfers ownership of the `HANDLE` to the file + // descriptor. DO NOT invoke `CloseHandle` on `hFile`. + let fd: CInt = _open_osfhandle(Int(bitPattern: hFile), _O_APPEND) + // NOTE: `_fdopen` transfers ownership of the file descriptor to the + // `FILE *`. DO NOT invoke `_close` on the `fd`. + guard let fp = _fdopen(fd, "w") else { + _close(fd) + return + } + defer { fclose(fp) } + + fputs(manifestToJSON(dumpInfo.package), fp) } - defer { fclose(fp) } - fputs(manifestToJSON(dumpInfo.package), fp) + dumpInfo = (package, handle) + atexit(dump) } - - dumpInfo = (package, handle) - atexit(dump) -} #else -private var dumpInfo: (package: Package, fileDesc: Int32)? -private func dumpPackageAtExit(_ package: Package, to fileDesc: Int32) { - func dump() { - guard let dumpInfo else { return } - guard let fd = fdopen(dumpInfo.fileDesc, "w") else { return } - fputs(manifestToJSON(dumpInfo.package), fd) - fclose(fd) + private var dumpInfo: (package: Package, fileDesc: Int32)? + private func dumpPackageAtExit(_ package: Package, to fileDesc: Int32) { + func dump() { + guard let dumpInfo else { return } + guard let fd = fdopen(dumpInfo.fileDesc, "w") else { return } + fputs(manifestToJSON(dumpInfo.package), fd) + fclose(fd) + } + dumpInfo = (package, fileDesc) + atexit(dump) } - dumpInfo = (package, fileDesc) - atexit(dump) -} #endif diff --git a/Sources/Runtimes/PackageDescription/PackageDescriptionSerialization.swift b/Sources/Runtimes/PackageDescription/PackageDescriptionSerialization.swift index 8ade7137333..1fbf6e02de1 100644 --- a/Sources/Runtimes/PackageDescription/PackageDescriptionSerialization.swift +++ b/Sources/Runtimes/PackageDescription/PackageDescriptionSerialization.swift @@ -11,9 +11,9 @@ //===----------------------------------------------------------------------===// #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import Foundation + @_implementationOnly import Foundation #else -import Foundation + import Foundation #endif enum Serialization { @@ -265,7 +265,7 @@ enum Serialization { let productType: ProductType #if ENABLE_APPLE_PRODUCT_TYPES - let settings: [ProductSetting] + let settings: [ProductSetting] #endif } @@ -307,123 +307,123 @@ enum Serialization { } #if ENABLE_APPLE_PRODUCT_TYPES -extension Serialization { - enum ProductSetting: Codable { - case bundleIdentifier(String) - case teamIdentifier(String) - case displayVersion(String) - case bundleVersion(String) - case iOSAppInfo(IOSAppInfo) - - struct IOSAppInfo: Codable { - var appIcon: AppIcon? - var accentColor: AccentColor? - var supportedDeviceFamilies: [DeviceFamily] - var supportedInterfaceOrientations: [InterfaceOrientation] - var capabilities: [Capability] = [] - var appCategory: AppCategory? - var additionalInfoPlistContentFilePath: String? - - enum AccentColor: Codable { - struct PresetColor: Codable { - var rawValue: String + extension Serialization { + enum ProductSetting: Codable { + case bundleIdentifier(String) + case teamIdentifier(String) + case displayVersion(String) + case bundleVersion(String) + case iOSAppInfo(IOSAppInfo) + + struct IOSAppInfo: Codable { + var appIcon: AppIcon? + var accentColor: AccentColor? + var supportedDeviceFamilies: [DeviceFamily] + var supportedInterfaceOrientations: [InterfaceOrientation] + var capabilities: [Capability] = [] + var appCategory: AppCategory? + var additionalInfoPlistContentFilePath: String? + + enum AccentColor: Codable { + struct PresetColor: Codable { + var rawValue: String + } + + case presetColor(PresetColor) + case asset(String) } - - case presetColor(PresetColor) - case asset(String) - } - - enum AppIcon: Codable { - struct PlaceholderIcon: Codable { - var rawValue: String + + enum AppIcon: Codable { + struct PlaceholderIcon: Codable { + var rawValue: String + } + + case placeholder(icon: PlaceholderIcon) + case asset(String) } - - case placeholder(icon: PlaceholderIcon) - case asset(String) - } - - enum DeviceFamily: String, Codable { - case phone - case pad - case mac - } - - struct DeviceFamilyCondition: Codable { - var deviceFamilies: [DeviceFamily] - } - - enum InterfaceOrientation: Codable { - case portrait(_ condition: DeviceFamilyCondition? = nil) - case portraitUpsideDown(_ condition: DeviceFamilyCondition? = nil) - case landscapeRight(_ condition: DeviceFamilyCondition? = nil) - case landscapeLeft(_ condition: DeviceFamilyCondition? = nil) - } - - enum Capability: Codable { - case appTransportSecurity(configuration: AppTransportSecurityConfiguration, _ condition: DeviceFamilyCondition? = nil) - case bluetoothAlways(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case calendars(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case camera(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case contacts(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case faceID(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case fileAccess(_ location: FileAccessLocation, mode: FileAccessMode, _ condition: DeviceFamilyCondition? = nil) - case incomingNetworkConnections(_ condition: DeviceFamilyCondition? = nil) - case localNetwork(purposeString: String, bonjourServiceTypes: [String]? = nil, _ condition: DeviceFamilyCondition? = nil) - case locationAlwaysAndWhenInUse(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case locationWhenInUse(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case mediaLibrary(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case microphone(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case motion(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case nearbyInteractionAllowOnce(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case outgoingNetworkConnections(_ condition: DeviceFamilyCondition? = nil) - case photoLibrary(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case photoLibraryAdd(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case reminders(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case speechRecognition(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case userTracking(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - } - - struct AppTransportSecurityConfiguration: Codable { - var allowsArbitraryLoadsInWebContent: Bool? = nil - var allowsArbitraryLoadsForMedia: Bool? = nil - var allowsLocalNetworking: Bool? = nil - var exceptionDomains: [ExceptionDomain]? = nil - var pinnedDomains: [PinnedDomain]? = nil - - struct ExceptionDomain: Codable { - var domainName: String - var includesSubdomains: Bool? = nil - var exceptionAllowsInsecureHTTPLoads: Bool? = nil - var exceptionMinimumTLSVersion: String? = nil - var exceptionRequiresForwardSecrecy: Bool? = nil - var requiresCertificateTransparency: Bool? = nil + + enum DeviceFamily: String, Codable { + case phone + case pad + case mac } - - struct PinnedDomain: Codable { - var domainName: String - var includesSubdomains : Bool? = nil - var pinnedCAIdentities : [[String: String]]? = nil - var pinnedLeafIdentities : [[String: String]]? = nil + + struct DeviceFamilyCondition: Codable { + var deviceFamilies: [DeviceFamily] + } + + enum InterfaceOrientation: Codable { + case portrait(_ condition: DeviceFamilyCondition? = nil) + case portraitUpsideDown(_ condition: DeviceFamilyCondition? = nil) + case landscapeRight(_ condition: DeviceFamilyCondition? = nil) + case landscapeLeft(_ condition: DeviceFamilyCondition? = nil) + } + + enum Capability: Codable { + case appTransportSecurity(configuration: AppTransportSecurityConfiguration, _ condition: DeviceFamilyCondition? = nil) + case bluetoothAlways(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case calendars(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case camera(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case contacts(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case faceID(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case fileAccess(_ location: FileAccessLocation, mode: FileAccessMode, _ condition: DeviceFamilyCondition? = nil) + case incomingNetworkConnections(_ condition: DeviceFamilyCondition? = nil) + case localNetwork(purposeString: String, bonjourServiceTypes: [String]? = nil, _ condition: DeviceFamilyCondition? = nil) + case locationAlwaysAndWhenInUse(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case locationWhenInUse(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case mediaLibrary(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case microphone(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case motion(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case nearbyInteractionAllowOnce(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case outgoingNetworkConnections(_ condition: DeviceFamilyCondition? = nil) + case photoLibrary(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case photoLibraryAdd(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case reminders(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case speechRecognition(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case userTracking(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + } + + struct AppTransportSecurityConfiguration: Codable { + var allowsArbitraryLoadsInWebContent: Bool? = nil + var allowsArbitraryLoadsForMedia: Bool? = nil + var allowsLocalNetworking: Bool? = nil + var exceptionDomains: [ExceptionDomain]? = nil + var pinnedDomains: [PinnedDomain]? = nil + + struct ExceptionDomain: Codable { + var domainName: String + var includesSubdomains: Bool? = nil + var exceptionAllowsInsecureHTTPLoads: Bool? = nil + var exceptionMinimumTLSVersion: String? = nil + var exceptionRequiresForwardSecrecy: Bool? = nil + var requiresCertificateTransparency: Bool? = nil + } + + struct PinnedDomain: Codable { + var domainName: String + var includesSubdomains: Bool? = nil + var pinnedCAIdentities: [[String: String]]? = nil + var pinnedLeafIdentities: [[String: String]]? = nil + } + } + + enum FileAccessLocation: String, Codable { + case userSelectedFiles + case downloadsFolder + case pictureFolder + case musicFolder + case moviesFolder + } + + enum FileAccessMode: String, Codable { + case readOnly + case readWrite + } + + struct AppCategory: Codable { + var rawValue: String } - } - - enum FileAccessLocation: String, Codable { - case userSelectedFiles - case downloadsFolder - case pictureFolder - case musicFolder - case moviesFolder - } - - enum FileAccessMode: String, Codable { - case readOnly - case readWrite - } - - struct AppCategory: Codable { - var rawValue: String } } } -} #endif diff --git a/Sources/Runtimes/PackageDescription/PackageDescriptionSerializationConversion.swift b/Sources/Runtimes/PackageDescription/PackageDescriptionSerializationConversion.swift index 09d4f73ebf3..abed059c754 100644 --- a/Sources/Runtimes/PackageDescription/PackageDescriptionSerializationConversion.swift +++ b/Sources/Runtimes/PackageDescription/PackageDescriptionSerializationConversion.swift @@ -245,7 +245,8 @@ extension Serialization.PluginCapability { init(_ capability: PackageDescription.Target.PluginCapability) { switch capability { case .buildTool: self = .buildTool - case .command(let intent, let permissions): self = .command( + case .command(let intent, let permissions): + self = .command( intent: .init(intent), permissions: permissions.map { .init($0) } ) @@ -266,7 +267,8 @@ extension Serialization.PluginCommandIntent { extension Serialization.PluginPermission { init(_ permission: PackageDescription.PluginPermission) { switch permission { - case .allowNetworkConnections(let scope, let reason): self = .allowNetworkConnections( + case .allowNetworkConnections(let scope, let reason): + self = .allowNetworkConnections( scope: .init(scope), reason: reason ) @@ -363,7 +365,7 @@ extension Serialization.Product { self.targets = executable.targets self.productType = .executable #if ENABLE_APPLE_PRODUCT_TYPES - self.settings = executable.settings.map { .init($0) } + self.settings = executable.settings.map { .init($0) } #endif } @@ -373,7 +375,7 @@ extension Serialization.Product { let libraryType = library.type.map { ProductType.LibraryType($0) } ?? .automatic self.productType = .library(type: libraryType) #if ENABLE_APPLE_PRODUCT_TYPES - self.settings = [] + self.settings = [] #endif } @@ -382,7 +384,7 @@ extension Serialization.Product { self.targets = plugin.targets self.productType = .plugin #if ENABLE_APPLE_PRODUCT_TYPES - self.settings = [] + self.settings = [] #endif } } @@ -430,211 +432,211 @@ extension Serialization.SystemPackageProvider { } #if ENABLE_APPLE_PRODUCT_TYPES -extension Serialization.ProductSetting { - init(_ setting: PackageDescription.ProductSetting) { - switch setting { - case .bundleIdentifier(let value): - self = .bundleIdentifier(value) - case .teamIdentifier(let value): - self = .teamIdentifier(value) - case .displayVersion(let value): - self = .displayVersion(value) - case .bundleVersion(let value): - self = .bundleVersion(value) - case .iOSAppInfo(let appInfo): - self = .iOSAppInfo(.init(appInfo)) + extension Serialization.ProductSetting { + init(_ setting: PackageDescription.ProductSetting) { + switch setting { + case .bundleIdentifier(let value): + self = .bundleIdentifier(value) + case .teamIdentifier(let value): + self = .teamIdentifier(value) + case .displayVersion(let value): + self = .displayVersion(value) + case .bundleVersion(let value): + self = .bundleVersion(value) + case .iOSAppInfo(let appInfo): + self = .iOSAppInfo(.init(appInfo)) + } } } -} -extension Serialization.ProductSetting.IOSAppInfo { - init(_ appInfo: PackageDescription.ProductSetting.IOSAppInfo) { - self.init( - appIcon: appInfo.appIcon.map { .init($0) }, - accentColor: appInfo.accentColor.map { .init($0) }, - supportedDeviceFamilies: appInfo.supportedDeviceFamilies.map { .init($0) }, - supportedInterfaceOrientations: appInfo.supportedInterfaceOrientations.map { .init($0) }, - capabilities: appInfo.capabilities.map { .init($0) }, - appCategory: appInfo.appCategory.map { .init($0) }, - additionalInfoPlistContentFilePath: appInfo.additionalInfoPlistContentFilePath - ) + extension Serialization.ProductSetting.IOSAppInfo { + init(_ appInfo: PackageDescription.ProductSetting.IOSAppInfo) { + self.init( + appIcon: appInfo.appIcon.map { .init($0) }, + accentColor: appInfo.accentColor.map { .init($0) }, + supportedDeviceFamilies: appInfo.supportedDeviceFamilies.map { .init($0) }, + supportedInterfaceOrientations: appInfo.supportedInterfaceOrientations.map { .init($0) }, + capabilities: appInfo.capabilities.map { .init($0) }, + appCategory: appInfo.appCategory.map { .init($0) }, + additionalInfoPlistContentFilePath: appInfo.additionalInfoPlistContentFilePath + ) + } } -} -extension Serialization.ProductSetting.IOSAppInfo.AccentColor { - init(_ color: PackageDescription.ProductSetting.IOSAppInfo.AccentColor) { - switch color { - case .presetColor(let color): - self = .presetColor(.init(color)) - case .asset(let value): - self = .asset(value) + extension Serialization.ProductSetting.IOSAppInfo.AccentColor { + init(_ color: PackageDescription.ProductSetting.IOSAppInfo.AccentColor) { + switch color { + case .presetColor(let color): + self = .presetColor(.init(color)) + case .asset(let value): + self = .asset(value) + } } } -} -extension Serialization.ProductSetting.IOSAppInfo.AccentColor.PresetColor { - init(_ color: PackageDescription.ProductSetting.IOSAppInfo.AccentColor.PresetColor) { - self.rawValue = color.rawValue + extension Serialization.ProductSetting.IOSAppInfo.AccentColor.PresetColor { + init(_ color: PackageDescription.ProductSetting.IOSAppInfo.AccentColor.PresetColor) { + self.rawValue = color.rawValue + } } -} -extension Serialization.ProductSetting.IOSAppInfo.AppIcon { - init(_ icon: PackageDescription.ProductSetting.IOSAppInfo.AppIcon) { - switch icon { - case .placeholder(icon: let icon): - self = .placeholder(icon: .init(icon)) - case .asset(let value): - self = .asset(value) + extension Serialization.ProductSetting.IOSAppInfo.AppIcon { + init(_ icon: PackageDescription.ProductSetting.IOSAppInfo.AppIcon) { + switch icon { + case .placeholder(icon: let icon): + self = .placeholder(icon: .init(icon)) + case .asset(let value): + self = .asset(value) + } } } -} -extension Serialization.ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon { - init(_ icon: PackageDescription.ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon) { - self.rawValue = icon.rawValue + extension Serialization.ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon { + init(_ icon: PackageDescription.ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon) { + self.rawValue = icon.rawValue + } } -} -extension Serialization.ProductSetting.IOSAppInfo.DeviceFamily { - init(_ deviceFamily: PackageDescription.ProductSetting.IOSAppInfo.DeviceFamily) { - switch deviceFamily { - case .phone: self = .phone - case .pad: self = .pad - case .mac: self = .mac + extension Serialization.ProductSetting.IOSAppInfo.DeviceFamily { + init(_ deviceFamily: PackageDescription.ProductSetting.IOSAppInfo.DeviceFamily) { + switch deviceFamily { + case .phone: self = .phone + case .pad: self = .pad + case .mac: self = .mac + } } } -} -extension Serialization.ProductSetting.IOSAppInfo.DeviceFamilyCondition { - init(_ condition: PackageDescription.ProductSetting.IOSAppInfo.DeviceFamilyCondition) { - self.init(deviceFamilies: condition.deviceFamilies.map { .init($0) }) + extension Serialization.ProductSetting.IOSAppInfo.DeviceFamilyCondition { + init(_ condition: PackageDescription.ProductSetting.IOSAppInfo.DeviceFamilyCondition) { + self.init(deviceFamilies: condition.deviceFamilies.map { .init($0) }) + } } -} -extension Serialization.ProductSetting.IOSAppInfo.InterfaceOrientation { - init(_ interfaceOrientation: PackageDescription.ProductSetting.IOSAppInfo.InterfaceOrientation) { - switch interfaceOrientation { - case .portrait(let condition): - self = .portrait(condition.map { .init($0) }) - case .portraitUpsideDown(let condition): - self = .portraitUpsideDown(condition.map { .init($0) }) - case .landscapeRight(let condition): - self = .landscapeRight(condition.map { .init($0) }) - case .landscapeLeft(let condition): - self = .landscapeLeft(condition.map { .init($0) }) + extension Serialization.ProductSetting.IOSAppInfo.InterfaceOrientation { + init(_ interfaceOrientation: PackageDescription.ProductSetting.IOSAppInfo.InterfaceOrientation) { + switch interfaceOrientation { + case .portrait(let condition): + self = .portrait(condition.map { .init($0) }) + case .portraitUpsideDown(let condition): + self = .portraitUpsideDown(condition.map { .init($0) }) + case .landscapeRight(let condition): + self = .landscapeRight(condition.map { .init($0) }) + case .landscapeLeft(let condition): + self = .landscapeLeft(condition.map { .init($0) }) + } } } -} -extension Serialization.ProductSetting.IOSAppInfo.Capability { - init(_ capability: PackageDescription.ProductSetting.IOSAppInfo.Capability) { - switch capability { - case .appTransportSecurity(configuration: let configuration, let condition): - self = .appTransportSecurity(configuration: .init(configuration), condition.map { .init($0) }) - case .bluetoothAlways(purposeString: let purposeString, let condition): - self = .bluetoothAlways(purposeString: purposeString, condition.map { .init($0) }) - case .calendars(purposeString: let purposeString, let condition): - self = .calendars(purposeString: purposeString, condition.map { .init($0) }) - case .camera(purposeString: let purposeString, let condition): - self = .camera(purposeString: purposeString, condition.map { .init($0) }) - case .contacts(purposeString: let purposeString, let condition): - self = .contacts(purposeString: purposeString, condition.map { .init($0) }) - case .faceID(purposeString: let purposeString, let condition): - self = .faceID(purposeString: purposeString, condition.map { .init($0) }) - case .fileAccess(let location, let mode, let condition): - self = .fileAccess(.init(location), mode: .init(mode), condition.map { .init($0) }) - case .incomingNetworkConnections(let condition): - self = .incomingNetworkConnections(condition.map { .init($0) }) - case .localNetwork(purposeString: let purposeString, bonjourServiceTypes: let bonjourServiceTypes, let condition): - self = .localNetwork(purposeString: purposeString, bonjourServiceTypes: bonjourServiceTypes, condition.map { .init($0) }) - case .locationAlwaysAndWhenInUse(purposeString: let purposeString, let condition): - self = .locationAlwaysAndWhenInUse(purposeString: purposeString, condition.map { .init($0) }) - case .locationWhenInUse(purposeString: let purposeString, let condition): - self = .locationWhenInUse(purposeString: purposeString, condition.map { .init($0) }) - case .mediaLibrary(purposeString: let purposeString, let condition): - self = .mediaLibrary(purposeString: purposeString, condition.map { .init($0) }) - case .microphone(purposeString: let purposeString, let condition): - self = .microphone(purposeString: purposeString, condition.map { .init($0) }) - case .motion(purposeString: let purposeString, let condition): - self = .motion(purposeString: purposeString, condition.map { .init($0) }) - case .nearbyInteractionAllowOnce(purposeString: let purposeString, let condition): - self = .nearbyInteractionAllowOnce(purposeString: purposeString, condition.map { .init($0) }) - case .outgoingNetworkConnections(let condition): - self = .outgoingNetworkConnections(condition.map { .init($0) }) - case .photoLibrary(purposeString: let purposeString, let condition): - self = .photoLibrary(purposeString: purposeString, condition.map { .init($0) }) - case .photoLibraryAdd(purposeString: let purposeString, let condition): - self = .photoLibraryAdd(purposeString: purposeString, condition.map { .init($0) }) - case .reminders(purposeString: let purposeString, let condition): - self = .reminders(purposeString: purposeString, condition.map { .init($0) }) - case .speechRecognition(purposeString: let purposeString, let condition): - self = .speechRecognition(purposeString: purposeString, condition.map { .init($0) }) - case .userTracking(purposeString: let purposeString, let condition): - self = .userTracking(purposeString: purposeString, condition.map { .init($0) }) - } - } -} - -extension Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration { - init(_ configuration: PackageDescription.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration) { - self.init( - allowsArbitraryLoadsInWebContent: configuration.allowsArbitraryLoadsInWebContent, - allowsArbitraryLoadsForMedia: configuration.allowsArbitraryLoadsForMedia, - allowsLocalNetworking: configuration.allowsLocalNetworking, - exceptionDomains: configuration.exceptionDomains?.map { .init($0) }, - pinnedDomains: configuration.pinnedDomains?.map { .init($0) } - ) - } -} - -extension Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.ExceptionDomain { - init(_ exceptionDomain: PackageDescription.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.ExceptionDomain) { - self.init( - domainName: exceptionDomain.domainName, - includesSubdomains: exceptionDomain.includesSubdomains, - exceptionAllowsInsecureHTTPLoads: exceptionDomain.exceptionAllowsInsecureHTTPLoads, - exceptionMinimumTLSVersion: exceptionDomain.exceptionMinimumTLSVersion, - exceptionRequiresForwardSecrecy: exceptionDomain.exceptionRequiresForwardSecrecy, - requiresCertificateTransparency: exceptionDomain.requiresCertificateTransparency - ) - } -} - -extension Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.PinnedDomain { - init(_ pinnedDomain: PackageDescription.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.PinnedDomain) { - self.init( - domainName: pinnedDomain.domainName, - includesSubdomains: pinnedDomain.includesSubdomains, - pinnedCAIdentities: pinnedDomain.pinnedCAIdentities, - pinnedLeafIdentities: pinnedDomain.pinnedLeafIdentities - ) - } -} - -extension Serialization.ProductSetting.IOSAppInfo.FileAccessLocation { - init(_ fileAccessLocation: PackageDescription.ProductSetting.IOSAppInfo.FileAccessLocation) { - switch fileAccessLocation { - case .userSelectedFiles: self = .userSelectedFiles - case .downloadsFolder: self = .downloadsFolder - case .pictureFolder: self = .pictureFolder - case .musicFolder: self = .musicFolder - case .moviesFolder: self = .moviesFolder - } - } -} - -extension Serialization.ProductSetting.IOSAppInfo.FileAccessMode { - init(_ fileAccessNode: PackageDescription.ProductSetting.IOSAppInfo.FileAccessMode) { - switch fileAccessNode { - case .readOnly: self = .readOnly - case .readWrite: self = .readWrite - } - } -} - -extension Serialization.ProductSetting.IOSAppInfo.AppCategory { - init(_ appCategory: PackageDescription.ProductSetting.IOSAppInfo.AppCategory) { - self.rawValue = appCategory.rawValue + extension Serialization.ProductSetting.IOSAppInfo.Capability { + init(_ capability: PackageDescription.ProductSetting.IOSAppInfo.Capability) { + switch capability { + case .appTransportSecurity(configuration: let configuration, let condition): + self = .appTransportSecurity(configuration: .init(configuration), condition.map { .init($0) }) + case .bluetoothAlways(purposeString: let purposeString, let condition): + self = .bluetoothAlways(purposeString: purposeString, condition.map { .init($0) }) + case .calendars(purposeString: let purposeString, let condition): + self = .calendars(purposeString: purposeString, condition.map { .init($0) }) + case .camera(purposeString: let purposeString, let condition): + self = .camera(purposeString: purposeString, condition.map { .init($0) }) + case .contacts(purposeString: let purposeString, let condition): + self = .contacts(purposeString: purposeString, condition.map { .init($0) }) + case .faceID(purposeString: let purposeString, let condition): + self = .faceID(purposeString: purposeString, condition.map { .init($0) }) + case .fileAccess(let location, let mode, let condition): + self = .fileAccess(.init(location), mode: .init(mode), condition.map { .init($0) }) + case .incomingNetworkConnections(let condition): + self = .incomingNetworkConnections(condition.map { .init($0) }) + case .localNetwork(purposeString: let purposeString, bonjourServiceTypes: let bonjourServiceTypes, let condition): + self = .localNetwork(purposeString: purposeString, bonjourServiceTypes: bonjourServiceTypes, condition.map { .init($0) }) + case .locationAlwaysAndWhenInUse(purposeString: let purposeString, let condition): + self = .locationAlwaysAndWhenInUse(purposeString: purposeString, condition.map { .init($0) }) + case .locationWhenInUse(purposeString: let purposeString, let condition): + self = .locationWhenInUse(purposeString: purposeString, condition.map { .init($0) }) + case .mediaLibrary(purposeString: let purposeString, let condition): + self = .mediaLibrary(purposeString: purposeString, condition.map { .init($0) }) + case .microphone(purposeString: let purposeString, let condition): + self = .microphone(purposeString: purposeString, condition.map { .init($0) }) + case .motion(purposeString: let purposeString, let condition): + self = .motion(purposeString: purposeString, condition.map { .init($0) }) + case .nearbyInteractionAllowOnce(purposeString: let purposeString, let condition): + self = .nearbyInteractionAllowOnce(purposeString: purposeString, condition.map { .init($0) }) + case .outgoingNetworkConnections(let condition): + self = .outgoingNetworkConnections(condition.map { .init($0) }) + case .photoLibrary(purposeString: let purposeString, let condition): + self = .photoLibrary(purposeString: purposeString, condition.map { .init($0) }) + case .photoLibraryAdd(purposeString: let purposeString, let condition): + self = .photoLibraryAdd(purposeString: purposeString, condition.map { .init($0) }) + case .reminders(purposeString: let purposeString, let condition): + self = .reminders(purposeString: purposeString, condition.map { .init($0) }) + case .speechRecognition(purposeString: let purposeString, let condition): + self = .speechRecognition(purposeString: purposeString, condition.map { .init($0) }) + case .userTracking(purposeString: let purposeString, let condition): + self = .userTracking(purposeString: purposeString, condition.map { .init($0) }) + } + } + } + + extension Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration { + init(_ configuration: PackageDescription.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration) { + self.init( + allowsArbitraryLoadsInWebContent: configuration.allowsArbitraryLoadsInWebContent, + allowsArbitraryLoadsForMedia: configuration.allowsArbitraryLoadsForMedia, + allowsLocalNetworking: configuration.allowsLocalNetworking, + exceptionDomains: configuration.exceptionDomains?.map { .init($0) }, + pinnedDomains: configuration.pinnedDomains?.map { .init($0) } + ) + } + } + + extension Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.ExceptionDomain { + init(_ exceptionDomain: PackageDescription.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.ExceptionDomain) { + self.init( + domainName: exceptionDomain.domainName, + includesSubdomains: exceptionDomain.includesSubdomains, + exceptionAllowsInsecureHTTPLoads: exceptionDomain.exceptionAllowsInsecureHTTPLoads, + exceptionMinimumTLSVersion: exceptionDomain.exceptionMinimumTLSVersion, + exceptionRequiresForwardSecrecy: exceptionDomain.exceptionRequiresForwardSecrecy, + requiresCertificateTransparency: exceptionDomain.requiresCertificateTransparency + ) + } + } + + extension Serialization.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.PinnedDomain { + init(_ pinnedDomain: PackageDescription.ProductSetting.IOSAppInfo.AppTransportSecurityConfiguration.PinnedDomain) { + self.init( + domainName: pinnedDomain.domainName, + includesSubdomains: pinnedDomain.includesSubdomains, + pinnedCAIdentities: pinnedDomain.pinnedCAIdentities, + pinnedLeafIdentities: pinnedDomain.pinnedLeafIdentities + ) + } + } + + extension Serialization.ProductSetting.IOSAppInfo.FileAccessLocation { + init(_ fileAccessLocation: PackageDescription.ProductSetting.IOSAppInfo.FileAccessLocation) { + switch fileAccessLocation { + case .userSelectedFiles: self = .userSelectedFiles + case .downloadsFolder: self = .downloadsFolder + case .pictureFolder: self = .pictureFolder + case .musicFolder: self = .musicFolder + case .moviesFolder: self = .moviesFolder + } + } + } + + extension Serialization.ProductSetting.IOSAppInfo.FileAccessMode { + init(_ fileAccessNode: PackageDescription.ProductSetting.IOSAppInfo.FileAccessMode) { + switch fileAccessNode { + case .readOnly: self = .readOnly + case .readWrite: self = .readWrite + } + } + } + + extension Serialization.ProductSetting.IOSAppInfo.AppCategory { + init(_ appCategory: PackageDescription.ProductSetting.IOSAppInfo.AppCategory) { + self.rawValue = appCategory.rawValue + } } -} #endif diff --git a/Sources/Runtimes/PackageDescription/PackageRequirement.swift b/Sources/Runtimes/PackageDescription/PackageRequirement.swift index dd507334eb8..ef3c2fc7d16 100644 --- a/Sources/Runtimes/PackageDescription/PackageRequirement.swift +++ b/Sources/Runtimes/PackageDescription/PackageRequirement.swift @@ -218,16 +218,15 @@ extension Range { /// /// - Parameter version: The minimum version for the version range. public static func upToNextMajor(from version: Version) -> Range where Bound == Version { - return version ..< Version(version.major + 1, 0, 0) + return version.. Range where Bound == Version { - return version ..< Version(version.major, version.minor + 1, 0) + return version.. DeviceFamilyCondition { + return DeviceFamilyCondition(deviceFamilies: deviceFamilies) } } - // Placeholder app icon using the app's accent color and specified icon. - case placeholder(icon: PlaceholderIcon) - // Named asset in an asset catalog. - case asset(String) - } - - /// Represents a family of device types that an application can support. - public enum DeviceFamily: String, Equatable { - case phone - case pad - case mac - } - - /// Represents a condition on a particular device family. - public struct DeviceFamilyCondition: Equatable { - public var deviceFamilies: [DeviceFamily] - - public init(deviceFamilies: [DeviceFamily]) { - self.deviceFamilies = deviceFamilies + + /// Represents a supported device interface orientation. + public enum InterfaceOrientation: Equatable { + case portrait(_ condition: DeviceFamilyCondition? = nil) + case portraitUpsideDown(_ condition: DeviceFamilyCondition? = nil) + case landscapeRight(_ condition: DeviceFamilyCondition? = nil) + case landscapeLeft(_ condition: DeviceFamilyCondition? = nil) + + public static var portrait: Self { portrait(nil) } + public static var portraitUpsideDown: Self { portraitUpsideDown(nil) } + public static var landscapeRight: Self { landscapeRight(nil) } + public static var landscapeLeft: Self { landscapeLeft(nil) } } - public static func when(deviceFamilies: [DeviceFamily]) -> DeviceFamilyCondition { - return DeviceFamilyCondition(deviceFamilies: deviceFamilies) + + /// A capability required by the device. + public enum Capability: Equatable { + case appTransportSecurity(configuration: AppTransportSecurityConfiguration, _ condition: DeviceFamilyCondition? = nil) + case bluetoothAlways(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case calendars(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case camera(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case contacts(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case faceID(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case fileAccess(_ location: FileAccessLocation, mode: FileAccessMode, _ condition: DeviceFamilyCondition? = nil) + case incomingNetworkConnections(_ condition: DeviceFamilyCondition? = nil) + case localNetwork(purposeString: String, bonjourServiceTypes: [String]? = nil, _ condition: DeviceFamilyCondition? = nil) + case locationAlwaysAndWhenInUse(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case locationWhenInUse(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case mediaLibrary(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case microphone(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case motion(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case nearbyInteractionAllowOnce(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case outgoingNetworkConnections(_ condition: DeviceFamilyCondition? = nil) + case photoLibrary(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case photoLibraryAdd(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case reminders(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case speechRecognition(purposeString: String, _ condition: DeviceFamilyCondition? = nil) + case userTracking(purposeString: String, _ condition: DeviceFamilyCondition? = nil) } - } - - /// Represents a supported device interface orientation. - public enum InterfaceOrientation: Equatable { - case portrait(_ condition: DeviceFamilyCondition? = nil) - case portraitUpsideDown(_ condition: DeviceFamilyCondition? = nil) - case landscapeRight(_ condition: DeviceFamilyCondition? = nil) - case landscapeLeft(_ condition: DeviceFamilyCondition? = nil) - - public static var portrait: Self { portrait(nil) } - public static var portraitUpsideDown: Self { portraitUpsideDown(nil) } - public static var landscapeRight: Self { landscapeRight(nil) } - public static var landscapeLeft: Self { landscapeLeft(nil) } - } - - /// A capability required by the device. - public enum Capability: Equatable { - case appTransportSecurity(configuration: AppTransportSecurityConfiguration, _ condition: DeviceFamilyCondition? = nil) - case bluetoothAlways(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case calendars(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case camera(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case contacts(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case faceID(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case fileAccess(_ location: FileAccessLocation, mode: FileAccessMode, _ condition: DeviceFamilyCondition? = nil) - case incomingNetworkConnections(_ condition: DeviceFamilyCondition? = nil) - case localNetwork(purposeString: String, bonjourServiceTypes: [String]? = nil, _ condition: DeviceFamilyCondition? = nil) - case locationAlwaysAndWhenInUse(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case locationWhenInUse(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case mediaLibrary(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case microphone(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case motion(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case nearbyInteractionAllowOnce(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case outgoingNetworkConnections(_ condition: DeviceFamilyCondition? = nil) - case photoLibrary(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case photoLibraryAdd(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case reminders(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case speechRecognition(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - case userTracking(purposeString: String, _ condition: DeviceFamilyCondition? = nil) - } - - public struct AppTransportSecurityConfiguration: Equatable { - public var allowsArbitraryLoadsInWebContent: Bool? = nil - public var allowsArbitraryLoadsForMedia: Bool? = nil - public var allowsLocalNetworking: Bool? = nil - public var exceptionDomains: [ExceptionDomain]? = nil - public var pinnedDomains: [PinnedDomain]? = nil - - public struct ExceptionDomain: Equatable { - public var domainName: String - public var includesSubdomains: Bool? = nil - public var exceptionAllowsInsecureHTTPLoads: Bool? = nil - public var exceptionMinimumTLSVersion: String? = nil - public var exceptionRequiresForwardSecrecy: Bool? = nil - public var requiresCertificateTransparency: Bool? = nil - public init( - domainName: String, - includesSubdomains: Bool? = nil, - exceptionAllowsInsecureHTTPLoads: Bool? = nil, - exceptionMinimumTLSVersion: String? = nil, - exceptionRequiresForwardSecrecy: Bool? = nil, - requiresCertificateTransparency: Bool? = nil - ) { - self.domainName = domainName - self.includesSubdomains = includesSubdomains - self.exceptionAllowsInsecureHTTPLoads = exceptionAllowsInsecureHTTPLoads - self.exceptionMinimumTLSVersion = exceptionMinimumTLSVersion - self.exceptionRequiresForwardSecrecy = exceptionRequiresForwardSecrecy - self.requiresCertificateTransparency = requiresCertificateTransparency + public struct AppTransportSecurityConfiguration: Equatable { + public var allowsArbitraryLoadsInWebContent: Bool? = nil + public var allowsArbitraryLoadsForMedia: Bool? = nil + public var allowsLocalNetworking: Bool? = nil + public var exceptionDomains: [ExceptionDomain]? = nil + public var pinnedDomains: [PinnedDomain]? = nil + + public struct ExceptionDomain: Equatable { + public var domainName: String + public var includesSubdomains: Bool? = nil + public var exceptionAllowsInsecureHTTPLoads: Bool? = nil + public var exceptionMinimumTLSVersion: String? = nil + public var exceptionRequiresForwardSecrecy: Bool? = nil + public var requiresCertificateTransparency: Bool? = nil + + public init( + domainName: String, + includesSubdomains: Bool? = nil, + exceptionAllowsInsecureHTTPLoads: Bool? = nil, + exceptionMinimumTLSVersion: String? = nil, + exceptionRequiresForwardSecrecy: Bool? = nil, + requiresCertificateTransparency: Bool? = nil + ) { + self.domainName = domainName + self.includesSubdomains = includesSubdomains + self.exceptionAllowsInsecureHTTPLoads = exceptionAllowsInsecureHTTPLoads + self.exceptionMinimumTLSVersion = exceptionMinimumTLSVersion + self.exceptionRequiresForwardSecrecy = exceptionRequiresForwardSecrecy + self.requiresCertificateTransparency = requiresCertificateTransparency + } } - } - - public struct PinnedDomain: Equatable { - public var domainName: String - public var includesSubdomains : Bool? = nil - public var pinnedCAIdentities : [[String: String]]? = nil - public var pinnedLeafIdentities : [[String: String]]? = nil - + + public struct PinnedDomain: Equatable { + public var domainName: String + public var includesSubdomains: Bool? = nil + public var pinnedCAIdentities: [[String: String]]? = nil + public var pinnedLeafIdentities: [[String: String]]? = nil + + public init( + domainName: String, + includesSubdomains: Bool? = nil, + pinnedCAIdentities: [[String: String]]? = nil, + pinnedLeafIdentities: [[String: String]]? = nil + ) { + self.domainName = domainName + self.includesSubdomains = includesSubdomains + self.pinnedCAIdentities = pinnedCAIdentities + self.pinnedLeafIdentities = pinnedLeafIdentities + } + } + public init( - domainName: String, - includesSubdomains: Bool? = nil, - pinnedCAIdentities: [[String: String]]? = nil, - pinnedLeafIdentities: [[String: String]]? = nil + allowsArbitraryLoadsInWebContent: Bool? = nil, + allowsArbitraryLoadsForMedia: Bool? = nil, + allowsLocalNetworking: Bool? = nil, + exceptionDomains: [ExceptionDomain]? = nil, + pinnedDomains: [PinnedDomain]? = nil ) { - self.domainName = domainName - self.includesSubdomains = includesSubdomains - self.pinnedCAIdentities = pinnedCAIdentities - self.pinnedLeafIdentities = pinnedLeafIdentities + self.allowsArbitraryLoadsInWebContent = allowsArbitraryLoadsInWebContent + self.allowsArbitraryLoadsForMedia = allowsArbitraryLoadsForMedia + self.allowsLocalNetworking = allowsLocalNetworking + self.exceptionDomains = exceptionDomains + self.pinnedDomains = pinnedDomains } } - - public init( - allowsArbitraryLoadsInWebContent: Bool? = nil, - allowsArbitraryLoadsForMedia: Bool? = nil, - allowsLocalNetworking: Bool? = nil, - exceptionDomains: [ExceptionDomain]? = nil, - pinnedDomains: [PinnedDomain]? = nil - ) { - self.allowsArbitraryLoadsInWebContent = allowsArbitraryLoadsInWebContent - self.allowsArbitraryLoadsForMedia = allowsArbitraryLoadsForMedia - self.allowsLocalNetworking = allowsLocalNetworking - self.exceptionDomains = exceptionDomains - self.pinnedDomains = pinnedDomains - } - } - public enum FileAccessLocation: Equatable { - case userSelectedFiles - case downloadsFolder - case pictureFolder - case musicFolder - case moviesFolder - - var identifier: String { - switch self { - case .userSelectedFiles: - return "userSelectedFiles" - case .downloadsFolder: - return "downloadsFolder" - case .pictureFolder: - return "pictureFolder" - case .musicFolder: - return "musicFolder" - case .moviesFolder: - return "moviesFolder" + public enum FileAccessLocation: Equatable { + case userSelectedFiles + case downloadsFolder + case pictureFolder + case musicFolder + case moviesFolder + + var identifier: String { + switch self { + case .userSelectedFiles: + return "userSelectedFiles" + case .downloadsFolder: + return "downloadsFolder" + case .pictureFolder: + return "pictureFolder" + case .musicFolder: + return "musicFolder" + case .moviesFolder: + return "moviesFolder" + } } } - } - public enum FileAccessMode: Equatable { - case readOnly - case readWrite + public enum FileAccessMode: Equatable { + case readOnly + case readWrite - var identifier: String { - switch self { - case .readOnly: return "readOnly" - case .readWrite: return "readWrite" + var identifier: String { + switch self { + case .readOnly: return "readOnly" + case .readWrite: return "readWrite" + } } } - } - - public struct AppCategory: Equatable, ExpressibleByStringLiteral { - public var rawValue: String - public init(rawValue: String) { - self.rawValue = rawValue - } + public struct AppCategory: Equatable, ExpressibleByStringLiteral { + public var rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue + } - public init(stringLiteral value: StringLiteralType) { - self.init(rawValue: value) + public init(stringLiteral value: StringLiteralType) { + self.init(rawValue: value) + } } - } - public init( - appIcon: AppIcon?, - accentColor: AccentColor?, - supportedDeviceFamilies: [DeviceFamily], - supportedInterfaceOrientations: [InterfaceOrientation], - capabilities: [Capability], - appCategory: AppCategory?, - additionalInfoPlistContentFilePath: String? - ) { - self.appIcon = appIcon - self.accentColor = accentColor - self.supportedDeviceFamilies = supportedDeviceFamilies - self.supportedInterfaceOrientations = supportedInterfaceOrientations - self.capabilities = capabilities - self.appCategory = appCategory - self.additionalInfoPlistContentFilePath = additionalInfoPlistContentFilePath + public init( + appIcon: AppIcon?, + accentColor: AccentColor?, + supportedDeviceFamilies: [DeviceFamily], + supportedInterfaceOrientations: [InterfaceOrientation], + capabilities: [Capability], + appCategory: AppCategory?, + additionalInfoPlistContentFilePath: String? + ) { + self.appIcon = appIcon + self.accentColor = accentColor + self.supportedDeviceFamilies = supportedDeviceFamilies + self.supportedInterfaceOrientations = supportedInterfaceOrientations + self.capabilities = capabilities + self.appCategory = appCategory + self.additionalInfoPlistContentFilePath = additionalInfoPlistContentFilePath + } } } -} #else -// This has to be defined at least as SPI because some of the methods that are -// SPI use it, but it doesn't contain anything when Apple product types aren't -// enabled. -@_spi(PackageProductSettings) -public enum ProductSetting: Equatable { } + // This has to be defined at least as SPI because some of the methods that are + // SPI use it, but it doesn't contain anything when Apple product types aren't + // enabled. + @_spi(PackageProductSettings) + public enum ProductSetting: Equatable {} #endif #if ENABLE_APPLE_PRODUCT_TYPES -extension ProductSetting.IOSAppInfo.AccentColor.PresetColor { - public static var blue: Self { .init(rawValue: "blue") } - public static var brown: Self { .init(rawValue: "brown") } - public static var cyan: Self { .init(rawValue: "cyan") } - public static var green: Self { .init(rawValue: "green") } - public static var indigo: Self { .init(rawValue: "indigo") } - public static var mint: Self { .init(rawValue: "mint") } - public static var orange: Self { .init(rawValue: "orange") } - public static var pink: Self { .init(rawValue: "pink") } - public static var purple: Self { .init(rawValue: "purple") } - public static var red: Self { .init(rawValue: "red") } - public static var teal: Self { .init(rawValue: "teal") } - public static var yellow: Self { .init(rawValue: "yellow") } -} + extension ProductSetting.IOSAppInfo.AccentColor.PresetColor { + public static var blue: Self { .init(rawValue: "blue") } + public static var brown: Self { .init(rawValue: "brown") } + public static var cyan: Self { .init(rawValue: "cyan") } + public static var green: Self { .init(rawValue: "green") } + public static var indigo: Self { .init(rawValue: "indigo") } + public static var mint: Self { .init(rawValue: "mint") } + public static var orange: Self { .init(rawValue: "orange") } + public static var pink: Self { .init(rawValue: "pink") } + public static var purple: Self { .init(rawValue: "purple") } + public static var red: Self { .init(rawValue: "red") } + public static var teal: Self { .init(rawValue: "teal") } + public static var yellow: Self { .init(rawValue: "yellow") } + } -extension ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon { - public static var bandage: Self { .init(rawValue: "bandage")} - public static var barChart: Self { .init(rawValue: "barChart")} - public static var beachball: Self { .init(rawValue: "beachball")} - public static var bicycle: Self { .init(rawValue: "bicycle")} - public static var binoculars: Self { .init(rawValue: "binoculars")} - public static var bird: Self { .init(rawValue: "bird") } - public static var boat: Self { .init(rawValue: "boat")} - public static var bowl: Self { .init(rawValue: "bowl")} - public static var box: Self { .init(rawValue: "box")} - public static var bunny: Self { .init(rawValue: "bunny")} - public static var butterfly: Self { .init(rawValue: "butterfly")} - public static var calculator: Self { .init(rawValue: "calculator")} - public static var calendar: Self { .init(rawValue: "calendar")} - public static var camera: Self { .init(rawValue: "camera")} - public static var car: Self { .init(rawValue: "car")} - public static var carrot: Self { .init(rawValue: "carrot")} - public static var cat: Self { .init(rawValue: "cat")} - public static var chatMessage: Self { .init(rawValue: "chatMessage")} - public static var checkmark: Self { .init(rawValue: "checkmark")} - public static var clock: Self { .init(rawValue: "clock")} - public static var cloud: Self { .init(rawValue: "cloud")} - public static var coffee: Self { .init(rawValue: "coffee")} - public static var coins: Self { .init(rawValue: "coins")} - public static var dog: Self { .init(rawValue: "dog")} - public static var earth: Self { .init(rawValue: "earth")} - public static var flower: Self { .init(rawValue: "flower")} - public static var gamepad: Self { .init(rawValue: "gamepad")} - public static var gift: Self { .init(rawValue: "gift")} - public static var heart: Self { .init(rawValue: "heart")} - public static var images: Self { .init(rawValue: "images")} - public static var leaf: Self { .init(rawValue: "leaf")} - public static var lightningBolt: Self { .init(rawValue: "lightningBolt")} - public static var location: Self { .init(rawValue: "location")} - public static var magicWand: Self { .init(rawValue: "magicWand")} - public static var map: Self { .init(rawValue: "map")} - public static var mic: Self { .init(rawValue: "mic")} - public static var moon: Self { .init(rawValue: "moon")} - public static var movieReel: Self { .init(rawValue: "movieReel")} - public static var note: Self { .init(rawValue: "note")} - public static var openBook: Self { .init(rawValue: "openBook")} - public static var palette: Self { .init(rawValue: "palette")} - public static var paper: Self { .init(rawValue: "paper")} - public static var pencil: Self { .init(rawValue: "pencil")} - public static var plane: Self { .init(rawValue: "plane")} - public static var rocket: Self { .init(rawValue: "rocket")} - public static var running: Self { .init(rawValue: "running")} - public static var sandwich: Self { .init(rawValue: "sandwich")} - public static var smiley: Self { .init(rawValue: "smiley")} - public static var sparkle: Self { .init(rawValue: "sparkle")} - public static var star: Self { .init(rawValue: "star")} - public static var sun: Self { .init(rawValue: "sun")} - public static var tv: Self { .init(rawValue: "tv")} - public static var twoPeople: Self { .init(rawValue: "twoPeople")} - public static var weights: Self { .init(rawValue: "weights")} -} + extension ProductSetting.IOSAppInfo.AppIcon.PlaceholderIcon { + public static var bandage: Self { .init(rawValue: "bandage") } + public static var barChart: Self { .init(rawValue: "barChart") } + public static var beachball: Self { .init(rawValue: "beachball") } + public static var bicycle: Self { .init(rawValue: "bicycle") } + public static var binoculars: Self { .init(rawValue: "binoculars") } + public static var bird: Self { .init(rawValue: "bird") } + public static var boat: Self { .init(rawValue: "boat") } + public static var bowl: Self { .init(rawValue: "bowl") } + public static var box: Self { .init(rawValue: "box") } + public static var bunny: Self { .init(rawValue: "bunny") } + public static var butterfly: Self { .init(rawValue: "butterfly") } + public static var calculator: Self { .init(rawValue: "calculator") } + public static var calendar: Self { .init(rawValue: "calendar") } + public static var camera: Self { .init(rawValue: "camera") } + public static var car: Self { .init(rawValue: "car") } + public static var carrot: Self { .init(rawValue: "carrot") } + public static var cat: Self { .init(rawValue: "cat") } + public static var chatMessage: Self { .init(rawValue: "chatMessage") } + public static var checkmark: Self { .init(rawValue: "checkmark") } + public static var clock: Self { .init(rawValue: "clock") } + public static var cloud: Self { .init(rawValue: "cloud") } + public static var coffee: Self { .init(rawValue: "coffee") } + public static var coins: Self { .init(rawValue: "coins") } + public static var dog: Self { .init(rawValue: "dog") } + public static var earth: Self { .init(rawValue: "earth") } + public static var flower: Self { .init(rawValue: "flower") } + public static var gamepad: Self { .init(rawValue: "gamepad") } + public static var gift: Self { .init(rawValue: "gift") } + public static var heart: Self { .init(rawValue: "heart") } + public static var images: Self { .init(rawValue: "images") } + public static var leaf: Self { .init(rawValue: "leaf") } + public static var lightningBolt: Self { .init(rawValue: "lightningBolt") } + public static var location: Self { .init(rawValue: "location") } + public static var magicWand: Self { .init(rawValue: "magicWand") } + public static var map: Self { .init(rawValue: "map") } + public static var mic: Self { .init(rawValue: "mic") } + public static var moon: Self { .init(rawValue: "moon") } + public static var movieReel: Self { .init(rawValue: "movieReel") } + public static var note: Self { .init(rawValue: "note") } + public static var openBook: Self { .init(rawValue: "openBook") } + public static var palette: Self { .init(rawValue: "palette") } + public static var paper: Self { .init(rawValue: "paper") } + public static var pencil: Self { .init(rawValue: "pencil") } + public static var plane: Self { .init(rawValue: "plane") } + public static var rocket: Self { .init(rawValue: "rocket") } + public static var running: Self { .init(rawValue: "running") } + public static var sandwich: Self { .init(rawValue: "sandwich") } + public static var smiley: Self { .init(rawValue: "smiley") } + public static var sparkle: Self { .init(rawValue: "sparkle") } + public static var star: Self { .init(rawValue: "star") } + public static var sun: Self { .init(rawValue: "sun") } + public static var tv: Self { .init(rawValue: "tv") } + public static var twoPeople: Self { .init(rawValue: "twoPeople") } + public static var weights: Self { .init(rawValue: "weights") } + } -extension ProductSetting.IOSAppInfo.AppCategory { - public static var books: Self { .init(rawValue: "public.app-category.books") } - public static var business: Self { .init(rawValue: "public.app-category.business") } - public static var developerTools: Self { .init(rawValue: "public.app-category.developer-tools") } - public static var education: Self { .init(rawValue: "public.app-category.education") } - public static var entertainment: Self { .init(rawValue: "public.app-category.entertainment") } - public static var finance: Self { .init(rawValue: "public.app-category.finance") } - public static var foodAndDrink: Self { .init(rawValue: "public.app-category.food-and-drink") } - public static var graphicsDesign: Self { .init(rawValue: "public.app-category.graphics-design") } - public static var healthcareFitness: Self { .init(rawValue: "public.app-category.healthcare-fitness") } - public static var lifestyle: Self { .init(rawValue: "public.app-category.lifestyle") } - public static var magazinesAndNewspapers: Self { .init(rawValue: "public.app-category.magazines-and-newspapers") } - public static var medical: Self { .init(rawValue: "public.app-category.medical") } - public static var music: Self { .init(rawValue: "public.app-category.music") } - public static var navigation: Self { .init(rawValue: "public.app-category.navigation") } - public static var news: Self { .init(rawValue: "public.app-category.news") } - public static var photography: Self { .init(rawValue: "public.app-category.photography") } - public static var productivity: Self { .init(rawValue: "public.app-category.productivity") } - public static var reference: Self { .init(rawValue: "public.app-category.reference") } - public static var shopping: Self { .init(rawValue: "public.app-category.shopping") } - public static var socialNetworking: Self { .init(rawValue: "public.app-category.social-networking") } - public static var sports: Self { .init(rawValue: "public.app-category.sports") } - public static var travel: Self { .init(rawValue: "public.app-category.travel") } - public static var utilities: Self { .init(rawValue: "public.app-category.utilities") } - public static var video: Self { .init(rawValue: "public.app-category.video") } - public static var weather: Self { .init(rawValue: "public.app-category.weather") } - - // Games - public static var games: Self { .init(rawValue: "public.app-category.games") } - // Games subcategories - public static var actionGames: Self { .init(rawValue: "public.app-category.action-games") } - public static var adventureGames: Self { .init(rawValue: "public.app-category.adventure-games") } - public static var arcadeGames: Self { .init(rawValue: "public.app-category.arcade-games") } - public static var boardGames: Self { .init(rawValue: "public.app-category.board-games") } - public static var cardGames: Self { .init(rawValue: "public.app-category.card-games") } - public static var casinoGames: Self { .init(rawValue: "public.app-category.casino-games") } - public static var diceGames: Self { .init(rawValue: "public.app-category.dice-games") } - public static var educationalGames: Self { .init(rawValue: "public.app-category.educational-games") } - public static var familyGames: Self { .init(rawValue: "public.app-category.family-games") } - public static var kidsGames: Self { .init(rawValue: "public.app-category.kids-games") } - public static var musicGames: Self { .init(rawValue: "public.app-category.music-games") } - public static var puzzleGames: Self { .init(rawValue: "public.app-category.puzzle-games") } - public static var racingGames: Self { .init(rawValue: "public.app-category.racing-games") } - public static var rolePlayingGames: Self { .init(rawValue: "public.app-category.role-playing-games") } - public static var simulationGames: Self { .init(rawValue: "public.app-category.simulation-games") } - public static var sportsGames: Self { .init(rawValue: "public.app-category.sports-games") } - public static var strategyGames: Self { .init(rawValue: "public.app-category.strategy-games") } - public static var triviaGames: Self { .init(rawValue: "public.app-category.trivia-games") } - public static var wordGames: Self { .init(rawValue: "public.app-category.word-games") } -} + extension ProductSetting.IOSAppInfo.AppCategory { + public static var books: Self { .init(rawValue: "public.app-category.books") } + public static var business: Self { .init(rawValue: "public.app-category.business") } + public static var developerTools: Self { .init(rawValue: "public.app-category.developer-tools") } + public static var education: Self { .init(rawValue: "public.app-category.education") } + public static var entertainment: Self { .init(rawValue: "public.app-category.entertainment") } + public static var finance: Self { .init(rawValue: "public.app-category.finance") } + public static var foodAndDrink: Self { .init(rawValue: "public.app-category.food-and-drink") } + public static var graphicsDesign: Self { .init(rawValue: "public.app-category.graphics-design") } + public static var healthcareFitness: Self { .init(rawValue: "public.app-category.healthcare-fitness") } + public static var lifestyle: Self { .init(rawValue: "public.app-category.lifestyle") } + public static var magazinesAndNewspapers: Self { .init(rawValue: "public.app-category.magazines-and-newspapers") } + public static var medical: Self { .init(rawValue: "public.app-category.medical") } + public static var music: Self { .init(rawValue: "public.app-category.music") } + public static var navigation: Self { .init(rawValue: "public.app-category.navigation") } + public static var news: Self { .init(rawValue: "public.app-category.news") } + public static var photography: Self { .init(rawValue: "public.app-category.photography") } + public static var productivity: Self { .init(rawValue: "public.app-category.productivity") } + public static var reference: Self { .init(rawValue: "public.app-category.reference") } + public static var shopping: Self { .init(rawValue: "public.app-category.shopping") } + public static var socialNetworking: Self { .init(rawValue: "public.app-category.social-networking") } + public static var sports: Self { .init(rawValue: "public.app-category.sports") } + public static var travel: Self { .init(rawValue: "public.app-category.travel") } + public static var utilities: Self { .init(rawValue: "public.app-category.utilities") } + public static var video: Self { .init(rawValue: "public.app-category.video") } + public static var weather: Self { .init(rawValue: "public.app-category.weather") } + + // Games + public static var games: Self { .init(rawValue: "public.app-category.games") } + // Games subcategories + public static var actionGames: Self { .init(rawValue: "public.app-category.action-games") } + public static var adventureGames: Self { .init(rawValue: "public.app-category.adventure-games") } + public static var arcadeGames: Self { .init(rawValue: "public.app-category.arcade-games") } + public static var boardGames: Self { .init(rawValue: "public.app-category.board-games") } + public static var cardGames: Self { .init(rawValue: "public.app-category.card-games") } + public static var casinoGames: Self { .init(rawValue: "public.app-category.casino-games") } + public static var diceGames: Self { .init(rawValue: "public.app-category.dice-games") } + public static var educationalGames: Self { .init(rawValue: "public.app-category.educational-games") } + public static var familyGames: Self { .init(rawValue: "public.app-category.family-games") } + public static var kidsGames: Self { .init(rawValue: "public.app-category.kids-games") } + public static var musicGames: Self { .init(rawValue: "public.app-category.music-games") } + public static var puzzleGames: Self { .init(rawValue: "public.app-category.puzzle-games") } + public static var racingGames: Self { .init(rawValue: "public.app-category.racing-games") } + public static var rolePlayingGames: Self { .init(rawValue: "public.app-category.role-playing-games") } + public static var simulationGames: Self { .init(rawValue: "public.app-category.simulation-games") } + public static var sportsGames: Self { .init(rawValue: "public.app-category.sports-games") } + public static var strategyGames: Self { .init(rawValue: "public.app-category.strategy-games") } + public static var triviaGames: Self { .init(rawValue: "public.app-category.trivia-games") } + public static var wordGames: Self { .init(rawValue: "public.app-category.word-games") } + } #endif diff --git a/Sources/Runtimes/PackageDescription/Resource.swift b/Sources/Runtimes/PackageDescription/Resource.swift index 2271e17b49f..fcbd27f457f 100644 --- a/Sources/Runtimes/PackageDescription/Resource.swift +++ b/Sources/Runtimes/PackageDescription/Resource.swift @@ -46,7 +46,7 @@ public struct Resource: Sendable { /// The rule for the resource. let rule: String - + /// The path of the resource. let path: String diff --git a/Sources/Runtimes/PackageDescription/SupportedPlatforms.swift b/Sources/Runtimes/PackageDescription/SupportedPlatforms.swift index 43ecd00139d..aa2715bf0b2 100644 --- a/Sources/Runtimes/PackageDescription/SupportedPlatforms.swift +++ b/Sources/Runtimes/PackageDescription/SupportedPlatforms.swift @@ -285,7 +285,7 @@ public struct SupportedPlatform: Equatable, Sendable { /// - versionString: The minimum deployment target as a string representation of two or three dot-separated integers, such as `19.0.1`. /// - Returns: A `SupportedPlatform` instance. @available(_PackageDescription, introduced: 5.6) - public static func custom(_ platformName: String, versionString: String) -> SupportedPlatform { + public static func custom(_ platformName: String, versionString: String) -> SupportedPlatform { do { try CustomPlatformVersion.validateVersion(versionString) } catch { diff --git a/Sources/Runtimes/PackageDescription/Target.swift b/Sources/Runtimes/PackageDescription/Target.swift index 9c7183a82f4..56bc66f6834 100644 --- a/Sources/Runtimes/PackageDescription/Target.swift +++ b/Sources/Runtimes/PackageDescription/Target.swift @@ -200,7 +200,7 @@ public final class Target { /// The target's linker settings. @available(_PackageDescription, introduced: 5) public var linkerSettings: [LinkerSetting]? - + /// The checksum for the archive file that contains the referenced binary /// artifact. /// @@ -217,7 +217,7 @@ public final class Target { /// The uses of package plug-ins by the target. @available(_PackageDescription, introduced: 5.5) public var plugins: [PluginUsage]? - + /// A plug-in used in a target. @available(_PackageDescription, introduced: 5.5) public enum PluginUsage { @@ -275,68 +275,23 @@ public final class Target { switch type { case .regular, .executable, .test: precondition( - url == nil && - pkgConfig == nil && - providers == nil && - pluginCapability == nil && - checksum == nil + url == nil && pkgConfig == nil && providers == nil && pluginCapability == nil && checksum == nil ) case .system: precondition( - url == nil && - dependencies.isEmpty && - exclude.isEmpty && - sources == nil && - resources == nil && - publicHeadersPath == nil && - pluginCapability == nil && - cSettings == nil && - cxxSettings == nil && - swiftSettings == nil && - linkerSettings == nil && - checksum == nil && - plugins == nil + url == nil && dependencies.isEmpty && exclude.isEmpty && sources == nil && resources == nil && publicHeadersPath == nil && pluginCapability == nil && cSettings == nil && cxxSettings == nil && swiftSettings == nil && linkerSettings == nil && checksum == nil && plugins == nil ) case .binary: precondition( - dependencies.isEmpty && - exclude.isEmpty && - sources == nil && - resources == nil && - publicHeadersPath == nil && - pkgConfig == nil && - providers == nil && - pluginCapability == nil && - cSettings == nil && - cxxSettings == nil && - swiftSettings == nil && - linkerSettings == nil && - plugins == nil + dependencies.isEmpty && exclude.isEmpty && sources == nil && resources == nil && publicHeadersPath == nil && pkgConfig == nil && providers == nil && pluginCapability == nil && cSettings == nil && cxxSettings == nil && swiftSettings == nil && linkerSettings == nil && plugins == nil ) case .plugin: precondition( - url == nil && - resources == nil && - publicHeadersPath == nil && - pkgConfig == nil && - providers == nil && - pluginCapability != nil && - cSettings == nil && - cxxSettings == nil && - swiftSettings == nil && - linkerSettings == nil && - plugins == nil + url == nil && resources == nil && publicHeadersPath == nil && pkgConfig == nil && providers == nil && pluginCapability != nil && cSettings == nil && cxxSettings == nil && swiftSettings == nil && linkerSettings == nil && plugins == nil ) case .macro: precondition( - url == nil && - resources == nil && - publicHeadersPath == nil && - pkgConfig == nil && - providers == nil && - pluginCapability == nil && - cSettings == nil && - cxxSettings == nil + url == nil && resources == nil && publicHeadersPath == nil && pkgConfig == nil && providers == nil && pluginCapability == nil && cSettings == nil && cxxSettings == nil ) } } @@ -1050,7 +1005,8 @@ public final class Target { type: .system, packageAccess: false, pkgConfig: pkgConfig, - providers: providers) + providers: providers + ) } /// Creates a binary target that references a remote artifact. @@ -1079,7 +1035,8 @@ public final class Target { publicHeadersPath: nil, type: .binary, packageAccess: false, - checksum: checksum) + checksum: checksum + ) } /// Creates a binary target that references an artifact on disk. @@ -1104,9 +1061,10 @@ public final class Target { sources: nil, publicHeadersPath: nil, type: .binary, - packageAccess: false) + packageAccess: false + ) } - + /// Defines a new package plugin target. /// /// A plugin target provides custom build commands to SwiftPM (and to @@ -1167,7 +1125,8 @@ public final class Target { publicHeadersPath: nil, type: .plugin, packageAccess: false, - pluginCapability: capability) + pluginCapability: capability + ) } /// Defines a new package plug-in target. @@ -1232,7 +1191,8 @@ public final class Target { publicHeadersPath: nil, type: .plugin, packageAccess: packageAccess, - pluginCapability: capability) + pluginCapability: capability + ) } } @@ -1257,7 +1217,7 @@ extension Target.Dependency { /// - name: The name of the product. /// - package: The name of the package. /// - Returns: A `Target.Dependency` instance. -@available(_PackageDescription, obsoleted: 5.2, message: "the 'package' argument is mandatory as of tools version 5.2") + @available(_PackageDescription, obsoleted: 5.2, message: "the 'package' argument is mandatory as of tools version 5.2") public static func product(name: String, package: String? = nil) -> Target.Dependency { return .productItem(name: name, package: package, moduleAliases: nil, condition: nil) } @@ -1267,7 +1227,7 @@ extension Target.Dependency { /// - Parameter name: The name of the dependency, either a target or a product. /// - Returns: A `Target.Dependency` instance. /// The Swift Package Manager creates the by-name dependency after it has loaded the package graph. -@available(_PackageDescription, obsoleted: 5.3) + @available(_PackageDescription, obsoleted: 5.3) public static func byName(name: String) -> Target.Dependency { return .byNameItem(name: name, condition: nil) } @@ -1278,7 +1238,7 @@ extension Target.Dependency { /// - name: The name of the product. /// - package: The name of the package. /// - Returns: A `Target.Dependency` instance. -@available(_PackageDescription, introduced: 5.2, obsoleted: 5.3) + @available(_PackageDescription, introduced: 5.2, obsoleted: 5.3) public static func product( name: String, package: String @@ -1294,7 +1254,7 @@ extension Target.Dependency { /// dependency. For example, only apply a dependency for a specific /// platform. /// - Returns: A `Target.Dependency` instance. -@available(_PackageDescription, introduced: 5.3) + @available(_PackageDescription, introduced: 5.3) public static func target(name: String, condition: TargetDependencyCondition? = nil) -> Target.Dependency { return .targetItem(name: name, condition: condition) } @@ -1308,7 +1268,7 @@ extension Target.Dependency { /// dependency. For example, only apply a dependency for a specific /// platform. /// - Returns: A `Target.Dependency` instance. -@_disfavoredOverload + @_disfavoredOverload @available(_PackageDescription, introduced: 5.3, obsoleted: 5.7) public static func product( name: String, @@ -1327,12 +1287,12 @@ extension Target.Dependency { /// - condition: A condition that limits the application of the target dependency. For example, only apply a /// dependency for a specific platform. /// - Returns: A `Target.Dependency` instance. -@available(_PackageDescription, introduced: 5.7) + @available(_PackageDescription, introduced: 5.7) public static func product( - name: String, - package: String, - moduleAliases: [String: String]? = nil, - condition: TargetDependencyCondition? = nil + name: String, + package: String, + moduleAliases: [String: String]? = nil, + condition: TargetDependencyCondition? = nil ) -> Target.Dependency { return .productItem(name: name, package: package, moduleAliases: moduleAliases, condition: condition) } @@ -1349,7 +1309,7 @@ extension Target.Dependency { /// dependency. For example, only apply a dependency for a specific /// platform. /// - Returns: A `Target.Dependency` instance. -@available(_PackageDescription, introduced: 5.3) + @available(_PackageDescription, introduced: 5.3) public static func byName(name: String, condition: TargetDependencyCondition? = nil) -> Target.Dependency { return .byNameItem(name: name, condition: condition) } @@ -1412,7 +1372,7 @@ public struct TargetDependencyCondition: Sendable { } extension Target.PluginCapability { - + /// The plug-in is a build tool. /// /// The plug-in to apply to each target that uses it, and creates commands @@ -1535,7 +1495,6 @@ extension Target.PluginUsage { } } - // MARK: ExpressibleByStringLiteral /// `ExpressibleByStringLiteral` conformance. @@ -1561,4 +1520,3 @@ extension Target.PluginUsage: ExpressibleByStringLiteral { self = .plugin(name: value, package: nil) } } - diff --git a/Sources/Runtimes/PackageDescription/Version+StringLiteralConvertible.swift b/Sources/Runtimes/PackageDescription/Version+StringLiteralConvertible.swift index c3d01faf20c..27034156733 100644 --- a/Sources/Runtimes/PackageDescription/Version+StringLiteralConvertible.swift +++ b/Sources/Runtimes/PackageDescription/Version+StringLiteralConvertible.swift @@ -62,7 +62,7 @@ extension Version: LosslessStringConvertible { versionCoreIdentifiers.count == 3, // Major, minor, and patch versions must be ASCII numbers, according to the semantic versioning standard. // Converting each identifier from a substring to an integer doubles as checking if the identifiers have non-numeric characters. - let major = Int(versionCoreIdentifiers[0]), + let major = Int(versionCoreIdentifiers[0]), let minor = Int(versionCoreIdentifiers[1]), let patch = Int(versionCoreIdentifiers[2]) else { return nil } @@ -74,7 +74,7 @@ extension Version: LosslessStringConvertible { if let prereleaseDelimiterIndex { let prereleaseStartIndex = versionString.index(after: prereleaseDelimiterIndex) let prereleaseIdentifiers = versionString[prereleaseStartIndex..<(metadataDelimiterIndex ?? versionString.endIndex)].split(separator: ".", omittingEmptySubsequences: false) - guard prereleaseIdentifiers.allSatisfy({ $0.allSatisfy({ $0.isLetter || $0.isNumber || $0 == "-" })}) else { return nil } + guard prereleaseIdentifiers.allSatisfy({ $0.allSatisfy({ $0.isLetter || $0.isNumber || $0 == "-" }) }) else { return nil } self.prereleaseIdentifiers = prereleaseIdentifiers.map { String($0) } } else { self.prereleaseIdentifiers = [] @@ -83,7 +83,7 @@ extension Version: LosslessStringConvertible { if let metadataDelimiterIndex { let metadataStartIndex = versionString.index(after: metadataDelimiterIndex) let buildMetadataIdentifiers = versionString[metadataStartIndex...].split(separator: ".", omittingEmptySubsequences: false) - guard buildMetadataIdentifiers.allSatisfy({ $0.allSatisfy({ $0.isLetter || $0.isNumber || $0 == "-" })}) else { return nil } + guard buildMetadataIdentifiers.allSatisfy({ $0.allSatisfy({ $0.isLetter || $0.isNumber || $0 == "-" }) }) else { return nil } self.buildMetadataIdentifiers = buildMetadataIdentifiers.map { String($0) } } else { self.buildMetadataIdentifiers = [] diff --git a/Sources/Runtimes/PackageDescription/Version.swift b/Sources/Runtimes/PackageDescription/Version.swift index b777a241919..45729df54ad 100644 --- a/Sources/Runtimes/PackageDescription/Version.swift +++ b/Sources/Runtimes/PackageDescription/Version.swift @@ -94,7 +94,7 @@ public struct Version: Sendable { extension Version: Comparable { // Although `Comparable` inherits from `Equatable`, it does not provide a new default implementation of `==`, but instead uses `Equatable`'s default synthesised implementation. The compiler-synthesised `==`` is composed of [member-wise comparisons](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0185-synthesize-equatable-hashable.md#implementation-details), which leads to a false `false` when 2 semantic versions differ by only their build metadata identifiers, contradicting SemVer 2.0.0's [comparison rules](https://semver.org/#spec-item-10). - + /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, `a == @@ -109,7 +109,7 @@ extension Version: Comparable { public static func == (lhs: Version, rhs: Version) -> Bool { !(lhs < rhs) && !(lhs > rhs) } - + /// Returns a Boolean value indicating whether the value of the first /// argument is less than that of the second argument. /// @@ -127,11 +127,11 @@ extension Version: Comparable { } guard lhs.prereleaseIdentifiers.count > 0 else { - return false // Non-prerelease lhs >= potentially prerelease rhs + return false // Non-prerelease lhs >= potentially prerelease rhs } guard rhs.prereleaseIdentifiers.count > 0 else { - return true // Prerelease lhs < non-prerelease rhs + return true // Prerelease lhs < non-prerelease rhs } for (lhsPrereleaseIdentifier, rhsPrereleaseIdentifier) in zip(lhs.prereleaseIdentifiers, rhs.prereleaseIdentifiers) { @@ -144,12 +144,13 @@ extension Version: Comparable { let rhsNumericPrereleaseIdentifier = Int(rhsPrereleaseIdentifier) if let lhsNumericPrereleaseIdentifier, - let rhsNumericPrereleaseIdentifier = rhsNumericPrereleaseIdentifier { + let rhsNumericPrereleaseIdentifier = rhsNumericPrereleaseIdentifier + { return lhsNumericPrereleaseIdentifier < rhsNumericPrereleaseIdentifier } else if lhsNumericPrereleaseIdentifier != nil { - return true // numeric pre-release < non-numeric pre-release + return true // numeric pre-release < non-numeric pre-release } else if rhsNumericPrereleaseIdentifier != nil { - return false // non-numeric pre-release > numeric pre-release + return false // non-numeric pre-release > numeric pre-release } else { return lhsPrereleaseIdentifier < rhsPrereleaseIdentifier } diff --git a/Sources/Runtimes/PackageDescription/WarningLevel.swift b/Sources/Runtimes/PackageDescription/WarningLevel.swift index 1d4a953fc32..6bd40ac106a 100644 --- a/Sources/Runtimes/PackageDescription/WarningLevel.swift +++ b/Sources/Runtimes/PackageDescription/WarningLevel.swift @@ -11,7 +11,7 @@ /// The level at which a compiler warning should be treated. /// -/// This enum is used with the `SwiftSetting.treatAllWarnings(as:_:)` and +/// This enum is used with the `SwiftSetting.treatAllWarnings(as:_:)` and /// `SwiftSetting.treatWarning(name:as:_:)` methods to control how warnings /// are handled during compilation. @available(_PackageDescription, introduced: 6.2) diff --git a/Sources/Runtimes/PackagePlugin/ArgumentExtractor.swift b/Sources/Runtimes/PackagePlugin/ArgumentExtractor.swift index d99f12dd5a8..d9e829ef288 100644 --- a/Sources/Runtimes/PackagePlugin/ArgumentExtractor.swift +++ b/Sources/Runtimes/PackagePlugin/ArgumentExtractor.swift @@ -45,13 +45,11 @@ public struct ArgumentExtractor { values.append(val) args.remove(at: idx) } - } - else if arg.starts(with: "--\(name)=") { + } else if arg.starts(with: "--\(name)=") { arg.removeFirst(2 + name.count + 1) values.append(arg) args.remove(at: idx) - } - else { + } else { idx += 1 } } @@ -67,8 +65,7 @@ public struct ArgumentExtractor { if arg == "--\(name)" { args.remove(at: idx) count += 1 - } - else { + } else { idx += 1 } } @@ -79,7 +76,7 @@ public struct ArgumentExtractor { /// /// This is based strictly on whether remaining arguments have a `--` prefix. public var unextractedOptionsOrFlags: [String] { - return args.filter{ $0.hasPrefix("--") } + return args.filter { $0.hasPrefix("--") } } /// Returns all remaining arguments. diff --git a/Sources/Runtimes/PackagePlugin/Context.swift b/Sources/Runtimes/PackagePlugin/Context.swift index 5944e653af7..95164eee76d 100644 --- a/Sources/Runtimes/PackagePlugin/Context.swift +++ b/Sources/Runtimes/PackagePlugin/Context.swift @@ -53,7 +53,7 @@ public struct PluginContext { public let pluginWorkDirectoryURL: URL /// Looks up and returns the path of a named command line executable. - /// + /// /// The executable must be provided by an executable target or binary /// target on which the package plugin target depends. This function throws /// an error if the tool cannot be found. The lookup is case sensitive. @@ -72,9 +72,9 @@ public struct PluginContext { } else { for dir in self.toolSearchDirectoryURLs { #if os(Windows) - let hostExecutableSuffix = ".exe" + let hostExecutableSuffix = ".exe" #else - let hostExecutableSuffix = "" + let hostExecutableSuffix = "" #endif let pathURL = dir.appendingPathComponent(name + hostExecutableSuffix) let path = try Path(url: pathURL) diff --git a/Sources/Runtimes/PackagePlugin/Diagnostics.swift b/Sources/Runtimes/PackagePlugin/Diagnostics.swift index 25b03190d7b..841e701d333 100644 --- a/Sources/Runtimes/PackagePlugin/Diagnostics.swift +++ b/Sources/Runtimes/PackagePlugin/Diagnostics.swift @@ -21,7 +21,7 @@ public struct Diagnostics { public enum Severity: String, Encodable { case error, warning, remark } - + /// Emits an error with a specified severity and message, and optional file path and line number. /// - Parameters: /// - severity: The severity of the diagnostic. diff --git a/Sources/Runtimes/PackagePlugin/PackageManagerProxy.swift b/Sources/Runtimes/PackagePlugin/PackageManagerProxy.swift index cbf19fee56e..9e650a7cd10 100644 --- a/Sources/Runtimes/PackagePlugin/PackageManagerProxy.swift +++ b/Sources/Runtimes/PackagePlugin/PackageManagerProxy.swift @@ -151,13 +151,13 @@ public struct PackageManager { /// Runs all, or a specified subset, of the unit tests of the package, after /// an incremental build if necessary. - /// + /// /// The is functionally the same as `swift test` on the command line. - /// + /// /// The returned test result includes any test failures. This method throws an /// error if the input parameters are invalid, or if the test cannot be /// started. - /// + /// /// The Swift package manager command-line interface, or any IDE, /// may show the progress of the tests as they happen. /// - Parameters: @@ -193,7 +193,7 @@ public struct PackageManager { public struct TestParameters { /// Whether to collect code coverage information while running tests. public var enableCodeCoverage: Bool - + /// Creates a new set of test parameters. /// - Parameter enableCodeCoverage: Whether to collect code coverage information while running tests. public init(enableCodeCoverage: Bool = false) { @@ -261,7 +261,7 @@ public struct PackageManager { /// Return a directory containing symbol graph files for the given target /// and options. - /// + /// /// If the symbol graphs need to be created or updated first, they will be. /// Swift package manager or an IDE may generate these symbol graph files /// in any way it sees fit. @@ -304,7 +304,7 @@ public struct PackageManager { /// A Boolean value that indicates whether to emit symbols for extensions to external types. public var emitExtensionBlocks: Bool - + /// Creates a new set of options for returning the symbol graph for a target. /// - Parameters: /// - minimumAccessLevel: The minimum access level of symbols to return. diff --git a/Sources/Runtimes/PackagePlugin/PackageModel.swift b/Sources/Runtimes/PackagePlugin/PackageModel.swift index 5712e99aa25..99e2101d236 100644 --- a/Sources/Runtimes/PackagePlugin/PackageModel.swift +++ b/Sources/Runtimes/PackagePlugin/PackageModel.swift @@ -38,7 +38,7 @@ public struct Package { public let origin: PackageOrigin /// The tools version specified by the resolved version of the package. - /// + /// /// Behavior is often gated on the tools version to make sure older /// packages continue to work as intended. public let toolsVersion: ToolsVersion @@ -97,7 +97,7 @@ public struct ToolsVersion { /// The patch version. public let patch: Int - + @_spi(PackagePluginInternal) public init(major: Int, minor: Int, patch: Int) { self.major = major self.minor = minor @@ -294,7 +294,7 @@ public enum ModuleKind { case test /// A module that contains code for a macro. @available(_PackageDescription, introduced: 5.9) - case macro // FIXME: This should really come from `CompilerPluginSupport` somehow, but we lack the infrastructure to allow that currently. + case macro // FIXME: This should really come from `CompilerPluginSupport` somehow, but we lack the infrastructure to allow that currently. } /// A target consisting of a source code module compiled using Swift. @@ -641,4 +641,3 @@ extension PathList: Sequence { return Iterator(paths: ArraySlice(self.paths.map { try! Path(url: $0) })) } } - diff --git a/Sources/Runtimes/PackagePlugin/Plugin.swift b/Sources/Runtimes/PackagePlugin/Plugin.swift index 22cf928bfe9..f492fd3f78f 100644 --- a/Sources/Runtimes/PackagePlugin/Plugin.swift +++ b/Sources/Runtimes/PackagePlugin/Plugin.swift @@ -12,33 +12,33 @@ import Foundation #if os(Windows) -@_implementationOnly import ucrt -@_implementationOnly import WinSDK + @_implementationOnly import ucrt + @_implementationOnly import WinSDK -internal func dup(_ fd: CInt) -> CInt { - return _dup(fd) -} -internal func dup2(_ fd1: CInt, _ fd2: CInt) -> CInt { - return _dup2(fd1, fd2) -} -internal func close(_ fd: CInt) -> CInt { - return _close(fd) -} -internal func fileno(_ fh: UnsafeMutablePointer?) -> CInt { - return _fileno(fh) -} + internal func dup(_ fd: CInt) -> CInt { + return _dup(fd) + } + internal func dup2(_ fd1: CInt, _ fd2: CInt) -> CInt { + return _dup2(fd1, fd2) + } + internal func close(_ fd: CInt) -> CInt { + return _close(fd) + } + internal func fileno(_ fh: UnsafeMutablePointer?) -> CInt { + return _fileno(fh) + } -internal func strerror(_ errno: CInt) -> String? { - // MSDN indicates that the returned string can have a maximum of 94 - // characters, so allocate 95 characters. - return withUnsafeTemporaryAllocation(of: wchar_t.self, capacity: 95) { - let result = _wcserror_s($0.baseAddress, $0.count, errno) - guard result == 0, let baseAddress = $0.baseAddress else { return nil } - return String(decodingCString: baseAddress, as: UTF16.self) + internal func strerror(_ errno: CInt) -> String? { + // MSDN indicates that the returned string can have a maximum of 94 + // characters, so allocate 95 characters. + return withUnsafeTemporaryAllocation(of: wchar_t.self, capacity: 95) { + let result = _wcserror_s($0.baseAddress, $0.count, errno) + guard result == 0, let baseAddress = $0.baseAddress else { return nil } + return String(decodingCString: baseAddress, as: UTF16.self) + } } -} #elseif canImport(Android) -import Android + import Android #endif // @@ -78,7 +78,7 @@ import Android // extension Plugin { - + /// The main entry point of the plugin. /// /// This sets up a communication channel with the plugin host and runs the main message loop. @@ -89,7 +89,7 @@ extension Plugin { guard inputFD >= 0 else { internalError("Could not duplicate `stdin`: \(describe(errno: errno)).") } - + // Having duplicated the original standard-input descriptor, we close // `stdin` so that attempts by the plugin to read console input (which // are usually a mistake) return errors instead of blocking. @@ -103,36 +103,36 @@ extension Plugin { guard outputFD >= 0 else { internalError("Could not dup `stdout`: \(describe(errno: errno)).") } - + // Having duplicated the original standard-output descriptor, redirect // `stdout` to `stderr` so that all free-form text output goes there. guard dup2(fileno(stderr), fileno(stdout)) >= 0 else { internalError("Could not dup2 `stdout` to `stderr`: \(describe(errno: errno)).") } - + // Turn off full buffering so printed text appears as soon as possible. // Windows is much less forgiving than other platforms. If line // buffering is enabled, we must provide a buffer and the size of the // buffer. As a result, on Windows, we completely disable all // buffering, which means that partial writes are possible. -#if os(Windows) - setvbuf(stdout, nil, _IONBF, 0) -#else - setvbuf(stdout, nil, _IOLBF, 0) -#endif + #if os(Windows) + setvbuf(stdout, nil, _IONBF, 0) + #else + setvbuf(stdout, nil, _IOLBF, 0) + #endif // Open a message channel for communicating with the plugin host. pluginHostConnection = PluginHostConnection( inputStream: FileHandle(fileDescriptor: inputFD), - outputStream: FileHandle(fileDescriptor: outputFD)) - + outputStream: FileHandle(fileDescriptor: outputFD) + ) + // Handle messages from the host until the input stream is closed, // indicating that we're done. while let message = try pluginHostConnection.waitForNextMessage() { do { try await handleMessage(message) - } - catch { + } catch { // Emit a diagnostic and indicate failure to the plugin host, // and exit with an error code. Diagnostics.error(String(describing: error)) @@ -140,11 +140,11 @@ extension Plugin { } } } - + /// Handles a single message received from the plugin host. fileprivate static func handleMessage(_ message: HostToPluginMessage) async throws { switch message { - + case .createBuildToolCommands(let wireInput, let rootPackageId, let targetId, let generatedSources, let generatedResources): // Deserialize the context from the wire input structures. The root // package is the one we'll set the context's `package` property to. @@ -168,7 +168,8 @@ extension Plugin { pluginWorkDirectoryURL: pluginWorkDirectory, accessibleTools: accessibleTools, toolSearchDirectories: toolSearchDirectories.map { try Path(url: $0) }, - toolSearchDirectoryURLs: toolSearchDirectories) + toolSearchDirectoryURLs: toolSearchDirectories + ) let pluginGeneratedSources = try generatedSources.map { try deserializer.url(for: $0) } let pluginGeneratedResources = try generatedResources.map { try deserializer.url(for: $0) } @@ -177,8 +178,7 @@ extension Plugin { pluginGeneratedSources: pluginGeneratedSources, pluginGeneratedResources: pluginGeneratedResources ) - } - catch { + } catch { internalError("Couldn’t deserialize input from host: \(error).") } @@ -196,10 +196,10 @@ extension Plugin { guard let plugin = plugin as? BuildToolPlugin else { throw PluginDeserializationError.missingBuildToolPluginProtocolConformance(protocolName: "BuildToolPlugin") } - + // Invoke the plugin to create build commands for the target. let generatedCommands = try await plugin.createBuildCommands(context: context, target: target) - + // Send each of the generated commands to the host. for command in generatedCommands { switch command { @@ -232,7 +232,7 @@ extension Plugin { try pluginHostConnection.sendMessage(message) } } - + // Exit with a zero exit code to indicate success. exit(0) @@ -246,7 +246,7 @@ extension Plugin { guard let plugin = plugin as? BuildToolPlugin else { throw PluginDeserializationError.missingBuildToolPluginProtocolConformance(protocolName: "BuildToolPlugin") } - + // Deserialize the context from the wire input structures, and create a record for us to pass to the XcodeProjectPlugin library. let record: XcodeProjectPluginInvocationRecord do { @@ -271,9 +271,9 @@ extension Plugin { xcodeTarget: xcodeTarget, pluginWorkDirectory: pluginWorkDirectory, accessibleTools: accessibleTools, - toolSearchDirectories: toolSearchDirectories) - } - catch { + toolSearchDirectories: toolSearchDirectories + ) + } catch { internalError("Couldn’t deserialize input from host: \(error).") } @@ -289,27 +289,31 @@ extension Plugin { executable: exec, arguments: args, environment: env, - workingDirectory: nil) + workingDirectory: nil + ) let message = PluginToHostMessage.defineBuildCommand( configuration: command, inputFiles: inputs, - outputFiles: outputs) + outputFiles: outputs + ) try pluginHostConnection.sendMessage(message) - + case let .prebuildCommand(name, exec, args, env, outdir): let command = PluginToHostMessage.CommandConfiguration( displayName: name, executable: exec, arguments: args, environment: env, - workingDirectory: nil) + workingDirectory: nil + ) let message = PluginToHostMessage.definePrebuildCommand( configuration: command, - outputFilesDirectory: outdir) + outputFilesDirectory: outdir + ) try pluginHostConnection.sendMessage(message) } } - + // Exit with a zero exit code to indicate success. exit(0) @@ -334,9 +338,9 @@ extension Plugin { pluginWorkDirectoryURL: pluginWorkDirectory, accessibleTools: accessibleTools, toolSearchDirectories: toolSearchDirectories.map { try Path(url: $0) }, - toolSearchDirectoryURLs: toolSearchDirectories) - } - catch { + toolSearchDirectoryURLs: toolSearchDirectories + ) + } catch { internalError("Couldn’t deserialize input from host: \(error).") } @@ -349,10 +353,10 @@ extension Plugin { guard let plugin = plugin as? CommandPlugin else { throw PluginDeserializationError.missingCommandPluginProtocolConformance(protocolName: "CommandPlugin") } - + // Invoke the plugin to perform its custom logic. try await plugin.performCommand(context: context, arguments: arguments) - + // Exit with a zero exit code to indicate success. exit(0) @@ -366,7 +370,7 @@ extension Plugin { guard let plugin = plugin as? CommandPlugin else { throw PluginDeserializationError.missingCommandPluginProtocolConformance(protocolName: "CommandPlugin") } - + // Deserialize the context from the wire input structures, and create a record for us to pass to the XcodeProjectPlugin library. let record: XcodeProjectPluginInvocationRecord do { @@ -386,9 +390,9 @@ extension Plugin { pluginWorkDirectory: pluginWorkDirectory, accessibleTools: accessibleTools, toolSearchDirectories: toolSearchDirectories, - arguments: arguments) - } - catch { + arguments: arguments + ) + } catch { internalError("Couldn’t deserialize input from host: \(error).") } @@ -407,15 +411,15 @@ extension Plugin { fputs("Internal Error: \(message)", stderr) exit(1) } - + // Private function to construct an error message from an `errno` code. fileprivate static func describe(errno: Int32) -> String { -#if os(Windows) - return strerror(errno) ?? String(errno) -#else - if let cStr = strerror(errno) { return String(cString: cStr) } - return String(describing: errno) -#endif + #if os(Windows) + return strerror(errno) ?? String(errno) + #else + if let cStr = strerror(errno) { return String(cString: cStr) } + return String(describing: errno) + #endif } } @@ -511,14 +515,14 @@ internal fileprivate(set) var pluginHostConnection: PluginHostConnection! typealias PluginHostConnection = MessageConnection -internal struct MessageConnection where TX: Encodable, RX: Decodable { +internal struct MessageConnection where TX: Encodable, RX: Decodable { let inputStream: FileHandle let outputStream: FileHandle func sendMessage(_ message: TX) throws { // Encode the message as JSON. let payload = try JSONEncoder().encode(message) - + // Write the header (a 64-bit length field in little endian byte order). var count = UInt64(littleEndian: UInt64(payload.count)) let header = Swift.withUnsafeBytes(of: &count) { Data($0) } @@ -528,16 +532,16 @@ internal struct MessageConnection where TX: Encodable, RX: Decodable { // Write the payload. try outputStream.write(contentsOf: payload) } - + func waitForNextMessage() throws -> RX? { // Read the header (a 64-bit length field in little endian byte order). guard let header = try inputStream.read(upToCount: 8) else { return nil } guard header.count == 8 else { throw PluginMessageError.truncatedHeader } - + // Decode the count. - let count = header.withUnsafeBytes{ $0.loadUnaligned(as: UInt64.self).littleEndian } + let count = header.withUnsafeBytes { $0.loadUnaligned(as: UInt64.self).littleEndian } guard count >= 2 else { throw PluginMessageError.invalidPayloadSize } @@ -560,10 +564,10 @@ internal struct MessageConnection where TX: Encodable, RX: Decodable { fileprivate func callEntryPoint(_ record: XcodeProjectPluginInvocationRecord, _ functionName: String) throws { #if !canImport(Darwin) - // Workaround for a compiler crash presumably related to Objective-C bridging on non-Darwin platforms (rdar://130826719&136043295) - typealias CallerFuncType = @convention(c) (UnsafeRawPointer) -> Any + // Workaround for a compiler crash presumably related to Objective-C bridging on non-Darwin platforms (rdar://130826719&136043295) + typealias CallerFuncType = @convention(c) (UnsafeRawPointer) -> Any #else - typealias CallerFuncType = @convention(c) (UnsafeRawPointer) -> (any Error)? + typealias CallerFuncType = @convention(c) (UnsafeRawPointer) -> (any Error)? #endif // Find the trampoline for the type of custom command (it's expected to be in the add-on library). @@ -574,15 +578,15 @@ fileprivate func callEntryPoint(_ record: XcodeProjectPluginInvocationRecord, _ // The caller function is expected to take a pointer to a XcodeProjectPluginInvocationRecord. It is expected to return nil on success or an error on failure, as there is no way of throwing form a C function. let recordPtr = UnsafeRawPointer(Unmanaged.passUnretained(record).toOpaque()) #if !canImport(Darwin) - // Workaround for a compiler crash presumably related to Objective-C bridging on non-Darwin platforms (rdar://130826719&136043295) - /*if let error = callerFunc(recordPtr) as! (any Error)? { - throw error - }*/ - fatalError("FIXME: Compiler crashes when trying to compile a call to callerFunc") + // Workaround for a compiler crash presumably related to Objective-C bridging on non-Darwin platforms (rdar://130826719&136043295) + /*if let error = callerFunc(recordPtr) as! (any Error)? { + throw error + }*/ + fatalError("FIXME: Compiler crashes when trying to compile a call to callerFunc") #else - if let error = callerFunc(recordPtr) { - throw error - } + if let error = callerFunc(recordPtr) { + throw error + } #endif } @@ -590,23 +594,23 @@ fileprivate enum Library: Sendable { @_alwaysEmitIntoClient public static func open() throws -> LibraryHandle { #if os(Windows) - guard let handle = GetModuleHandleW(nil) else { - throw LibraryOpenError(message: "GetModuleHandleW returned \(GetLastError())") - } - return LibraryHandle(rawValue: handle) + guard let handle = GetModuleHandleW(nil) else { + throw LibraryOpenError(message: "GetModuleHandleW returned \(GetLastError())") + } + return LibraryHandle(rawValue: handle) #else - guard let handle = dlopen(nil, RTLD_NOW | RTLD_LOCAL) else { - throw LibraryOpenError(message: String(cString: dlerror()!)) - } - return LibraryHandle(rawValue: handle) + guard let handle = dlopen(nil, RTLD_NOW | RTLD_LOCAL) else { + throw LibraryOpenError(message: String(cString: dlerror()!)) + } + return LibraryHandle(rawValue: handle) #endif } public static func lookup(_ handle: LibraryHandle, _ symbol: String) -> T? { #if os(Windows) - guard let ptr = GetProcAddress(handle.rawValue, symbol) else { return nil } + guard let ptr = GetProcAddress(handle.rawValue, symbol) else { return nil } #else - guard let ptr = dlsym(handle.rawValue, symbol) else { return nil } + guard let ptr = dlsym(handle.rawValue, symbol) else { return nil } #endif return unsafeBitCast(ptr, to: T.self) } @@ -627,9 +631,9 @@ fileprivate struct LibraryOpenError: Error, CustomStringConvertible, Sendable { fileprivate struct LibraryHandle: @unchecked Sendable { #if os(Windows) - @usableFromInline typealias PlatformHandle = HMODULE + @usableFromInline typealias PlatformHandle = HMODULE #else - @usableFromInline typealias PlatformHandle = UnsafeMutableRawPointer + @usableFromInline typealias PlatformHandle = UnsafeMutableRawPointer #endif fileprivate let rawValue: PlatformHandle diff --git a/Sources/Runtimes/PackagePlugin/PluginContextDeserializer.swift b/Sources/Runtimes/PackagePlugin/PluginContextDeserializer.swift index 1593d30f745..548d214f0ab 100644 --- a/Sources/Runtimes/PackagePlugin/PluginContextDeserializer.swift +++ b/Sources/Runtimes/PackagePlugin/PluginContextDeserializer.swift @@ -27,12 +27,12 @@ internal struct PluginContextDeserializer { var targetsById: [WireInput.Target.Id: Target] = [:] var xcodeProjectsById: [WireInput.XcodeProject.Id: XcodeProjectPluginInvocationRecord.XcodeProject] = [:] var xcodeTargetsById: [WireInput.XcodeTarget.Id: XcodeProjectPluginInvocationRecord.XcodeTarget] = [:] - + /// Initializes the deserializer with the given wire input. init(_ input: WireInput) { self.wireInput = input } - + /// Returns the `URL` that corresponds to the given ID (a small integer), /// or throws an error if the ID is invalid. The URL is deserialized on- /// demand if it hasn't already been deserialized. @@ -41,19 +41,19 @@ internal struct PluginContextDeserializer { guard id < wireInput.paths.count else { throw PluginDeserializationError.malformedInputJSON("invalid URL id (\(id))") } - + // Compose a path based on an optional base path and a subpath. let wirePath = wireInput.paths[id] - let basePath = try wireInput.paths[id].baseURLId.map{ try self.url(for: $0) } + let basePath = try wireInput.paths[id].baseURLId.map { try self.url(for: $0) } let path: URL if let basePath { path = basePath.appendingPathComponent(wirePath.subpath) } else { #if os(Windows) - // Windows does not have a single root path like UNIX, if this component has no base path, it IS the root and should not be joined with anything - path = URL(fileURLWithPath: wirePath.subpath) + // Windows does not have a single root path like UNIX, if this component has no base path, it IS the root and should not be joined with anything + path = URL(fileURLWithPath: wirePath.subpath) #else - path = URL(fileURLWithPath: "/").appendingPathComponent(wirePath.subpath) + path = URL(fileURLWithPath: "/").appendingPathComponent(wirePath.subpath) #endif } @@ -67,8 +67,9 @@ internal struct PluginContextDeserializer { /// demand if it hasn't already been deserialized. mutating func target(for id: WireInput.Target.Id, pluginGeneratedSources: [URL] = [], pluginGeneratedResources: [URL] = []) throws -> Target { if let target = targetsById[id], - target.sourceModule?.pluginGeneratedSources.count == pluginGeneratedSources.count, - target.sourceModule?.pluginGeneratedResources.count == pluginGeneratedResources.count { + target.sourceModule?.pluginGeneratedSources.count == pluginGeneratedSources.count, + target.sourceModule?.pluginGeneratedResources.count == pluginGeneratedResources.count + { return target } guard id < wireInput.targets.count else { @@ -89,23 +90,25 @@ internal struct PluginContextDeserializer { let directory = try self.url(for: wireTarget.directoryId) let target: Target switch wireTarget.info { - + case let .swiftSourceModuleInfo(moduleName, kind, sourceFiles, compilationConditions, linkedLibraries, linkedFrameworks): - let sourceFiles = FileList(try sourceFiles.map { - let path = try self.url(for: $0.basePathId).appendingPathComponent($0.name) - let type: FileType - switch $0.type { - case .source: - type = .source - case .header: - type = .header - case .resource: - type = .resource - case .unknown: - type = .unknown + let sourceFiles = FileList( + try sourceFiles.map { + let path = try self.url(for: $0.basePathId).appendingPathComponent($0.name) + let type: FileType + switch $0.type { + case .source: + type = .source + case .header: + type = .header + case .resource: + type = .resource + case .unknown: + type = .unknown + } + return File(url: path, type: type) } - return File(url: path, type: type) - }) + ) target = try SwiftSourceModuleTarget( id: String(id), name: wireTarget.name, @@ -124,21 +127,23 @@ internal struct PluginContextDeserializer { case let .clangSourceModuleInfo(moduleName, kind, sourceFiles, preprocessorDefinitions, headerSearchPaths, publicHeadersDirId, linkedLibraries, linkedFrameworks): let publicHeadersDir = try publicHeadersDirId.map { try self.url(for: $0) } - let sourceFiles = FileList(try sourceFiles.map { - let path = try self.url(for: $0.basePathId).appendingPathComponent($0.name) - let type: FileType - switch $0.type { - case .source: - type = .source - case .header: - type = .header - case .resource: - type = .resource - case .unknown: - type = .unknown + let sourceFiles = FileList( + try sourceFiles.map { + let path = try self.url(for: $0.basePathId).appendingPathComponent($0.name) + let type: FileType + switch $0.type { + case .source: + type = .source + case .header: + type = .header + case .resource: + type = .resource + case .unknown: + type = .unknown + } + return File(url: path, type: type) } - return File(url: path, type: type) - }) + ) target = try ClangSourceModuleTarget( id: String(id), name: wireTarget.name, @@ -183,7 +188,8 @@ internal struct PluginContextDeserializer { kind: artifactKind, origin: artifactOrigin, artifact: Path(url: artifact), - artifactURL: artifact) + artifactURL: artifact + ) case let .systemLibraryInfo(pkgConfig, compilerFlags, linkerFlags): target = try SystemLibraryTarget( @@ -194,9 +200,10 @@ internal struct PluginContextDeserializer { dependencies: dependencies, pkgConfig: pkgConfig, compilerFlags: compilerFlags, - linkerFlags: linkerFlags) + linkerFlags: linkerFlags + ) } - + targetsById[id] = target return target } @@ -211,7 +218,7 @@ internal struct PluginContextDeserializer { } let wireProduct = wireInput.products[id] - let targets: [Target] = try wireProduct.targetIds.map{ try self.target(for: $0) } + let targets: [Target] = try wireProduct.targetIds.map { try self.target(for: $0) } let product: Product switch wireProduct.info { @@ -221,7 +228,8 @@ internal struct PluginContextDeserializer { id: String(id), name: wireProduct.name, targets: targets, - mainTarget: mainTarget) + mainTarget: mainTarget + ) case .library(let type): let libraryKind: LibraryProduct.Kind @@ -237,9 +245,10 @@ internal struct PluginContextDeserializer { id: String(id), name: wireProduct.name, targets: targets, - kind: libraryKind) + kind: libraryKind + ) } - + productsById[id] = product return product } @@ -250,20 +259,23 @@ internal struct PluginContextDeserializer { mutating func package(for id: WireInput.Product.Id) throws -> Package { if let package = packagesById[id] { return package } guard id < wireInput.packages.count else { - throw PluginDeserializationError.malformedInputJSON("invalid package id (\(id))") } - + throw PluginDeserializationError.malformedInputJSON("invalid package id (\(id))") + } + let wirePackage = wireInput.packages[id] let directory = try self.url(for: wirePackage.directoryId) let toolsVersion = ToolsVersion( major: wirePackage.toolsVersion.major, minor: wirePackage.toolsVersion.minor, - patch: wirePackage.toolsVersion.patch) + patch: wirePackage.toolsVersion.patch + ) let dependencies: [PackageDependency] = try wirePackage.dependencies.map { .init(package: try self.package(for: $0.packageId)) } let products = try wirePackage.productIds.map { try self.product(for: $0) } let targets = try wirePackage.targetIds.map { try self.target(for: $0) } - let origin: PackageOrigin = switch wirePackage.origin { + let origin: PackageOrigin = + switch wirePackage.origin { case .root: .root case .local(let pathId): @@ -272,18 +284,19 @@ internal struct PluginContextDeserializer { .repository(url: url, displayVersion: displayVersion, scmRevision: scmRevision) case .registry(let identity, let displayVersion): .registry(identity: identity, displayVersion: displayVersion) - } + } let package = try Package( id: wirePackage.identity, displayName: wirePackage.displayName, directory: Path(url: directory), directoryURL: directory, - origin: origin, + origin: origin, toolsVersion: toolsVersion, dependencies: dependencies, products: products, - targets: targets) - + targets: targets + ) + packagesById[id] = package return package } @@ -293,8 +306,9 @@ internal struct PluginContextDeserializer { /// demand if it hasn't already been deserialized. mutating func xcodeTarget(for id: WireInput.XcodeTarget.Id, pluginGeneratedSources: [URL] = [], pluginGeneratedResources: [URL] = []) throws -> XcodeProjectPluginInvocationRecord.XcodeTarget { if let xcodeTarget = xcodeTargetsById[id], - xcodeTarget.pluginGeneratedSources.count == pluginGeneratedSources.count, - xcodeTarget.pluginGeneratedResources.count == pluginGeneratedResources.count { + xcodeTarget.pluginGeneratedSources.count == pluginGeneratedSources.count, + xcodeTarget.pluginGeneratedResources.count == pluginGeneratedResources.count + { return xcodeTarget } guard id < wireInput.xcodeTargets.count else { @@ -318,21 +332,23 @@ internal struct PluginContextDeserializer { } return .init(name: $0.name, kind: kind) } - let inputFiles = FileList(try wireXcodeTarget.inputFiles.map { - let path = try self.url(for: $0.basePathId).appendingPathComponent($0.name) - let type: FileType - switch $0.type { - case .source: - type = .source - case .header: - type = .header - case .resource: - type = .resource - case .unknown: - type = .unknown + let inputFiles = FileList( + try wireXcodeTarget.inputFiles.map { + let path = try self.url(for: $0.basePathId).appendingPathComponent($0.name) + let type: FileType + switch $0.type { + case .source: + type = .source + case .header: + type = .header + case .resource: + type = .resource + case .unknown: + type = .unknown + } + return .init(url: path, type: type) } - return .init(url: path, type: type) - }) + ) let xcodeTarget = XcodeProjectPluginInvocationRecord.XcodeTarget( id: String(id), displayName: wireXcodeTarget.displayName, @@ -352,19 +368,21 @@ internal struct PluginContextDeserializer { mutating func xcodeProject(for id: WireInput.XcodeProject.Id) throws -> XcodeProjectPluginInvocationRecord.XcodeProject { if let xcodeProject = xcodeProjectsById[id] { return xcodeProject } guard id < wireInput.xcodeProjects.count else { - throw PluginDeserializationError.malformedInputJSON("invalid Xcode project id (\(id))") } - + throw PluginDeserializationError.malformedInputJSON("invalid Xcode project id (\(id))") + } + let wireXcodeProject = wireInput.xcodeProjects[id] let directoryPath = try self.url(for: wireXcodeProject.directoryPathId) - let filePaths = PathList(try wireXcodeProject.urlIds.map{ try self.url(for: $0) }) + let filePaths = PathList(try wireXcodeProject.urlIds.map { try self.url(for: $0) }) let targets = try wireXcodeProject.targetIds.map { try self.xcodeTarget(for: $0) } let xcodeProject = XcodeProjectPluginInvocationRecord.XcodeProject( id: String(id), displayName: wireXcodeProject.displayName, directoryPathURL: directoryPath, filePaths: filePaths, - targets: targets) - + targets: targets + ) + xcodeProjectsById[id] = xcodeProject return xcodeProject } diff --git a/Sources/Runtimes/PackagePlugin/PluginMessages.swift b/Sources/Runtimes/PackagePlugin/PluginMessages.swift index 0f4c677eab4..8f689a738f8 100644 --- a/Sources/Runtimes/PackagePlugin/PluginMessages.swift +++ b/Sources/Runtimes/PackagePlugin/PluginMessages.swift @@ -14,7 +14,7 @@ import Foundation /// A message that the host can send to the plugin, including definitions of the corresponding serializable data structures. enum HostToPluginMessage: Codable { - + /// The host requests that the plugin create build commands (corresponding to a `.buildTool` capability) for a target in the package graph. case createBuildToolCommands( context: InputContext, @@ -39,301 +39,313 @@ enum HostToPluginMessage: Codable { /// The host requests that the plugin perform a user command (corresponding to a `.command` capability) on a package in the graph. case performXcodeProjectCommand(context: InputContext, rootProjectId: InputContext.XcodeProject.Id, arguments: [String]) - struct InputContext: Codable { - let paths: [URL] - let targets: [Target] - let products: [Product] - let packages: [Package] - let xcodeTargets: [XcodeTarget] - let xcodeProjects: [XcodeProject] - let pluginWorkDirId: URL.Id - let toolSearchDirIds: [URL.Id] - let accessibleTools: [String: Tool] - - // Wrapper struct for encoding information about a tool that's accessible to the plugin. - struct Tool: Codable { - let path: URL.Id - let triples: [String]? + struct InputContext: Codable { + let paths: [URL] + let targets: [Target] + let products: [Product] + let packages: [Package] + let xcodeTargets: [XcodeTarget] + let xcodeProjects: [XcodeProject] + let pluginWorkDirId: URL.Id + let toolSearchDirIds: [URL.Id] + let accessibleTools: [String: Tool] + + // Wrapper struct for encoding information about a tool that's accessible to the plugin. + struct Tool: Codable { + let path: URL.Id + let triples: [String]? + } + + /// A single absolute path in the wire structure, represented as a tuple + /// consisting of the ID of the base path and subpath off of that path. + /// This avoids repetition of path components in the wire representation. + struct URL: Codable { + typealias Id = Int + let baseURLId: URL.Id? + let subpath: String + } + + /// A package in the wire structure. All references to other entities are + /// their ID numbers. + struct Package: Codable { + typealias Id = Int + let identity: String + let displayName: String + let directoryId: URL.Id + let origin: Origin + let toolsVersion: ToolsVersion + let dependencies: [Dependency] + let productIds: [Product.Id] + let targetIds: [Target.Id] + + enum Origin: Codable { + case root + case local( + path: URL.Id + ) + case repository( + url: String, + displayVersion: String, + scmRevision: String + ) + case registry( + identity: String, + displayVersion: String + ) } - /// A single absolute path in the wire structure, represented as a tuple - /// consisting of the ID of the base path and subpath off of that path. - /// This avoids repetition of path components in the wire representation. - struct URL: Codable { - typealias Id = Int - let baseURLId: URL.Id? - let subpath: String + struct ToolsVersion: Codable { + let major: Int + let minor: Int + let patch: Int } - /// A package in the wire structure. All references to other entities are - /// their ID numbers. - struct Package: Codable { - typealias Id = Int - let identity: String - let displayName: String - let directoryId: URL.Id - let origin: Origin - let toolsVersion: ToolsVersion - let dependencies: [Dependency] - let productIds: [Product.Id] - let targetIds: [Target.Id] - - enum Origin: Codable { - case root - case local( - path: URL.Id) - case repository( - url: String, - displayVersion: String, - scmRevision: String) - case registry( - identity: String, - displayVersion: String) - } - - struct ToolsVersion: Codable { - let major: Int - let minor: Int - let patch: Int - } + /// A dependency on a package in the wire structure. All references to + /// other entities are ID numbers. + struct Dependency: Codable { + let packageId: Package.Id + } + } - /// A dependency on a package in the wire structure. All references to - /// other entities are ID numbers. - struct Dependency: Codable { - let packageId: Package.Id + /// A product in the wire structure. All references to other entities are + /// their ID numbers. + struct Product: Codable { + typealias Id = Int + let name: String + let targetIds: [Target.Id] + let info: ProductInfo + + /// Information for each type of product in the wire structure. All + /// references to other entities are their ID numbers. + enum ProductInfo: Codable { + case executable( + mainTargetId: Target.Id + ) + case library( + kind: LibraryKind + ) + + enum LibraryKind: Codable { + case `static` + case `dynamic` + case automatic } } + } - /// A product in the wire structure. All references to other entities are - /// their ID numbers. - struct Product: Codable { - typealias Id = Int - let name: String - let targetIds: [Target.Id] - let info: ProductInfo - - /// Information for each type of product in the wire structure. All - /// references to other entities are their ID numbers. - enum ProductInfo: Codable { - case executable( - mainTargetId: Target.Id) - case library( - kind: LibraryKind) - - enum LibraryKind: Codable { - case `static` - case `dynamic` - case automatic - } - } + /// A target in the wire structure. All references to other entities are + /// their ID numbers. + struct Target: Codable { + typealias Id = Int + let name: String + let directoryId: URL.Id + let dependencies: [Dependency] + let info: TargetInfo + + /// A dependency on either a target or a product in the wire structure. + /// All references to other entities are ID their numbers. + enum Dependency: Codable { + case target( + targetId: Target.Id + ) + case product( + productId: Product.Id + ) } - /// A target in the wire structure. All references to other entities are - /// their ID numbers. - struct Target: Codable { - typealias Id = Int - let name: String - let directoryId: URL.Id - let dependencies: [Dependency] - let info: TargetInfo - - /// A dependency on either a target or a product in the wire structure. - /// All references to other entities are ID their numbers. - enum Dependency: Codable { - case target( - targetId: Target.Id) - case product( - productId: Product.Id) + /// Type-specific information for a target in the wire structure. All + /// references to other entities are their ID numbers. + enum TargetInfo: Codable { + case swiftSourceModuleInfo( + moduleName: String, + kind: SourceModuleKind, + sourceFiles: [File], + compilationConditions: [String], + linkedLibraries: [String], + linkedFrameworks: [String] + ) + + case clangSourceModuleInfo( + moduleName: String, + kind: SourceModuleKind, + sourceFiles: [File], + preprocessorDefinitions: [String], + headerSearchPaths: [String], + publicHeadersDirId: URL.Id?, + linkedLibraries: [String], + linkedFrameworks: [String] + ) + + case binaryArtifactInfo( + kind: BinaryArtifactKind, + origin: BinaryArtifactOrigin, + artifactId: URL.Id + ) + + case systemLibraryInfo( + pkgConfig: String?, + compilerFlags: [String], + linkerFlags: [String] + ) + + enum SourceModuleKind: String, Codable { + case generic + case executable + case snippet + case test + case macro } - - /// Type-specific information for a target in the wire structure. All - /// references to other entities are their ID numbers. - enum TargetInfo: Codable { - case swiftSourceModuleInfo( - moduleName: String, - kind: SourceModuleKind, - sourceFiles: [File], - compilationConditions: [String], - linkedLibraries: [String], - linkedFrameworks: [String]) - - case clangSourceModuleInfo( - moduleName: String, - kind: SourceModuleKind, - sourceFiles: [File], - preprocessorDefinitions: [String], - headerSearchPaths: [String], - publicHeadersDirId: URL.Id?, - linkedLibraries: [String], - linkedFrameworks: [String]) - - case binaryArtifactInfo( - kind: BinaryArtifactKind, - origin: BinaryArtifactOrigin, - artifactId: URL.Id) - - case systemLibraryInfo( - pkgConfig: String?, - compilerFlags: [String], - linkerFlags: [String]) - - enum SourceModuleKind: String, Codable { - case generic - case executable - case snippet - case test - case macro - } - enum BinaryArtifactKind: Codable { - case xcframework - case artifactsArchive - } + enum BinaryArtifactKind: Codable { + case xcframework + case artifactsArchive + } - enum BinaryArtifactOrigin: Codable { - case local - case remote(url: String) - } + enum BinaryArtifactOrigin: Codable { + case local + case remote(url: String) } } - - /// A typed file in the wire structure. All references to other entities are - /// their ID numbers. - struct File: Codable { - let basePathId: URL.Id - let name: String - let type: FileType + } - enum FileType: String, Codable { - case source - case header - case resource - case unknown - } + /// A typed file in the wire structure. All references to other entities are + /// their ID numbers. + struct File: Codable { + let basePathId: URL.Id + let name: String + let type: FileType + + enum FileType: String, Codable { + case source + case header + case resource + case unknown } + } - /// An Xcode project in the wire structure. All references to other entities are their ID numbers. - struct XcodeProject: Codable { - typealias Id = Int - let displayName: String - let directoryPathId: URL.Id - let dependencies: [Dependency] - let urlIds: [URL.Id] - let targetIds: [XcodeTarget.Id] - - /// A dependency on a package or project in the wire structure. All references to - /// other entities are ID numbers. - enum Dependency: Codable { - case package(Package.Id) - case xcodeProject(XcodeProject.Id) - } + /// An Xcode project in the wire structure. All references to other entities are their ID numbers. + struct XcodeProject: Codable { + typealias Id = Int + let displayName: String + let directoryPathId: URL.Id + let dependencies: [Dependency] + let urlIds: [URL.Id] + let targetIds: [XcodeTarget.Id] + + /// A dependency on a package or project in the wire structure. All references to + /// other entities are ID numbers. + enum Dependency: Codable { + case package(Package.Id) + case xcodeProject(XcodeProject.Id) } + } - /// A target in the wire structure. All references to other entities are - /// their ID numbers. - struct XcodeTarget: Codable { - typealias Id = Int - let displayName: String - let product: XcodeProduct? - let dependencies: [Dependency] - let inputFiles: [File] - - /// A product in the wire structure. - struct XcodeProduct: Codable { - let name: String - let kind: Kind - public enum Kind: Codable { - case application - case executable - case framework - case library - case other(String) - } + /// A target in the wire structure. All references to other entities are + /// their ID numbers. + struct XcodeTarget: Codable { + typealias Id = Int + let displayName: String + let product: XcodeProduct? + let dependencies: [Dependency] + let inputFiles: [File] + + /// A product in the wire structure. + struct XcodeProduct: Codable { + let name: String + let kind: Kind + public enum Kind: Codable { + case application + case executable + case framework + case library + case other(String) } + } - /// A dependency on either a target or a product in the wire structure. - /// All references to other entities are ID their numbers. - enum Dependency: Codable { - case target( - targetId: XcodeTarget.Id) - case product( - productId: Product.Id) - } + /// A dependency on either a target or a product in the wire structure. + /// All references to other entities are ID their numbers. + enum Dependency: Codable { + case target( + targetId: XcodeTarget.Id + ) + case product( + productId: Product.Id + ) } } - + } + /// A response to a request to run a build operation. case buildOperationResponse(result: BuildResult) - struct BuildResult: Codable { - var succeeded: Bool - var logText: String - var builtArtifacts: [BuiltArtifact] - - struct BuiltArtifact: Codable { - var path: URL - var kind: Kind - - enum Kind: String, Codable { - case executable - case dynamicLibrary - case staticLibrary - } + struct BuildResult: Codable { + var succeeded: Bool + var logText: String + var builtArtifacts: [BuiltArtifact] + + struct BuiltArtifact: Codable { + var path: URL + var kind: Kind + + enum Kind: String, Codable { + case executable + case dynamicLibrary + case staticLibrary } } + } /// A response to a request to run a test operation. case testOperationResponse(result: TestResult) - struct TestResult: Codable { - var succeeded: Bool - var testTargets: [TestTarget] - var codeCoverageDataFile: String? + struct TestResult: Codable { + var succeeded: Bool + var testTargets: [TestTarget] + var codeCoverageDataFile: String? - struct TestTarget: Codable { + struct TestTarget: Codable { + var name: String + var testCases: [TestCase] + + struct TestCase: Codable { var name: String - var testCases: [TestCase] - - struct TestCase: Codable { + var tests: [Test] + + struct Test: Codable { var name: String - var tests: [Test] - - struct Test: Codable { - var name: String - var result: Result - var duration: Double - - enum Result: String, Codable { - case succeeded - case skipped - case failed - } + var result: Result + var duration: Double + + enum Result: String, Codable { + case succeeded + case skipped + case failed } } } } - + } + /// A response to a request for symbol graph information for a target. case symbolGraphResponse(result: SymbolGraphResult) - - struct SymbolGraphResult: Codable { - var directoryPath: URL - } - + + struct SymbolGraphResult: Codable { + var directoryPath: URL + } + /// A response of an error while trying to complete a request. case errorResponse(error: String) } - /// A message that the plugin can send to the host. enum PluginToHostMessage: Codable { - + /// The plugin emits a diagnostic. case emitDiagnostic(severity: DiagnosticSeverity, message: String, file: String?, line: Int?) - enum DiagnosticSeverity: String, Codable { - case error, warning, remark - } + enum DiagnosticSeverity: String, Codable { + case error, warning, remark + } /// The plugin emits a progress message. case emitProgress(message: String) @@ -343,64 +355,64 @@ enum PluginToHostMessage: Codable { /// The plugin defines a prebuild command. case definePrebuildCommand(configuration: CommandConfiguration, outputFilesDirectory: URL) - - struct CommandConfiguration: Codable { - var version = 2 - var displayName: String? - var executable: URL - var arguments: [String] - var environment: [String: String] - var workingDirectory: URL? - } - + + struct CommandConfiguration: Codable { + var version = 2 + var displayName: String? + var executable: URL + var arguments: [String] + var environment: [String: String] + var workingDirectory: URL? + } + /// The plugin is requesting that a build operation be run. case buildOperationRequest(subset: BuildSubset, parameters: BuildParameters) - - enum BuildSubset: Codable { - case all(includingTests: Bool) - case product(String) - case target(String) - } - struct BuildParameters: Codable { - var configuration: Configuration - enum Configuration: String, Codable { - case debug, release, inherit - } - var logging: LogVerbosity - enum LogVerbosity: String, Codable { - case concise, verbose, debug - } - var echoLogs: Bool - var otherCFlags: [String] - var otherCxxFlags: [String] - var otherSwiftcFlags: [String] - var otherLinkerFlags: [String] + enum BuildSubset: Codable { + case all(includingTests: Bool) + case product(String) + case target(String) + } + + struct BuildParameters: Codable { + var configuration: Configuration + enum Configuration: String, Codable { + case debug, release, inherit + } + var logging: LogVerbosity + enum LogVerbosity: String, Codable { + case concise, verbose, debug } + var echoLogs: Bool + var otherCFlags: [String] + var otherCxxFlags: [String] + var otherSwiftcFlags: [String] + var otherLinkerFlags: [String] + } /// The plugin is requesting that a test operation be run. case testOperationRequest(subset: TestSubset, parameters: TestParameters) - enum TestSubset: Codable { - case all - case filtered([String]) - } + enum TestSubset: Codable { + case all + case filtered([String]) + } - struct TestParameters: Codable { - var enableCodeCoverage: Bool - } + struct TestParameters: Codable { + var enableCodeCoverage: Bool + } /// The plugin is requesting symbol graph information for a given target and set of options. case symbolGraphRequest(targetName: String, options: SymbolGraphOptions) - struct SymbolGraphOptions: Codable { - var minimumAccessLevel: AccessLevel - enum AccessLevel: String, Codable { - case `private`, `fileprivate`, `internal`, `package`, `public`, `open` - } - var includeInheritedDocs: Bool? = true - var includeSynthesized: Bool - var includeSPI: Bool - var emitExtensionBlocks: Bool + struct SymbolGraphOptions: Codable { + var minimumAccessLevel: AccessLevel + enum AccessLevel: String, Codable { + case `private`, `fileprivate`, `internal`, `package`, `public`, `open` } + var includeInheritedDocs: Bool? = true + var includeSynthesized: Bool + var includeSPI: Bool + var emitExtensionBlocks: Bool + } } diff --git a/Sources/Runtimes/PackagePlugin/Protocols.swift b/Sources/Runtimes/PackagePlugin/Protocols.swift index e4a2471abc1..a7b31cf6f5e 100644 --- a/Sources/Runtimes/PackagePlugin/Protocols.swift +++ b/Sources/Runtimes/PackagePlugin/Protocols.swift @@ -20,7 +20,6 @@ /// For example, the way to instantiate and run a plugin. public protocol Plugin { - /// Instantiates the plugin. /// /// This happens once per invocation of the plugin. @@ -54,7 +53,7 @@ public protocol CommandPlugin: Plugin { /// This is the same for all kinds of plugins, and provides access to the package graph, /// to cache directories, and so on. context: PluginContext, - + /// Any literal arguments passed after the verb in the command invocation. arguments: [String] ) async throws @@ -64,7 +63,7 @@ public protocol CommandPlugin: Plugin { var packageManager: PackageManager { get } } -extension CommandPlugin { +extension CommandPlugin { /// A proxy to the Swift Package Manager or IDE hosting the command plugin, /// through which the plugin can ask for specialized information or actions. public var packageManager: PackageManager { diff --git a/Sources/Runtimes/PackagePlugin/Utilities.swift b/Sources/Runtimes/PackagePlugin/Utilities.swift index bba632c5ed7..2c80e6f942a 100644 --- a/Sources/Runtimes/PackagePlugin/Utilities.swift +++ b/Sources/Runtimes/PackagePlugin/Utilities.swift @@ -62,17 +62,17 @@ extension Target { var visited = Set() func dependencyClosure(for target: Target) -> [Target] { guard visited.insert(target.id).inserted else { return [] } - return target.dependencies.flatMap{ dependencyClosure(for: $0) } + [target] + return target.dependencies.flatMap { dependencyClosure(for: $0) } + [target] } func dependencyClosure(for dependency: TargetDependency) -> [Target] { switch dependency { case .target(let target): return dependencyClosure(for: target) case .product(let product): - return product.targets.flatMap{ dependencyClosure(for: $0) } + return product.targets.flatMap { dependencyClosure(for: $0) } } } - return self.dependencies.flatMap{ dependencyClosure(for: $0) } + return self.dependencies.flatMap { dependencyClosure(for: $0) } } /// Convenience accessor which casts the receiver to`SourceModuleTarget`, if possible. @@ -98,6 +98,6 @@ extension SourceModuleTarget { /// A possibly empty list of source files in the target that have the given /// filename suffix. public func sourceFiles(withSuffix suffix: String) -> FileList { - return FileList(self.sourceFiles.filter{ $0.url.lastPathComponent.hasSuffix(suffix) }) + return FileList(self.sourceFiles.filter { $0.url.lastPathComponent.hasSuffix(suffix) }) } } diff --git a/Sources/SPMBuildCore/BinaryTarget+Extensions.swift b/Sources/SPMBuildCore/BinaryTarget+Extensions.swift index d5286127a9e..d5c74a35c94 100644 --- a/Sources/SPMBuildCore/BinaryTarget+Extensions.swift +++ b/Sources/SPMBuildCore/BinaryTarget+Extensions.swift @@ -44,17 +44,18 @@ extension BinaryModule { // At the moment we return at most a single library. let metadata = try XCFrameworkMetadata.parse(fileSystem: fileSystem, rootPath: self.artifactPath) // Filter the libraries that are relevant to the triple. - guard let library = metadata.libraries.first(where: { - $0.platform == triple.asXCFrameworkPlatformString && - $0.variant == triple.environment?.asXCFrameworkPlatformVariantString && - $0.architectures.contains(triple.archName) - }) else { + guard + let library = metadata.libraries.first(where: { + $0.platform == triple.asXCFrameworkPlatformString && $0.variant == triple.environment?.asXCFrameworkPlatformVariantString && $0.architectures.contains(triple.archName) + }) + else { return [] } // Construct a LibraryInfo for the library. let libraryDir = self.artifactPath.appending(component: library.libraryIdentifier) let libraryFile = try AbsolutePath(validating: library.libraryPath, relativeTo: libraryDir) - let headersDirs = try library.headersPath + let headersDirs = + try library.headersPath .map { [try AbsolutePath(validating: $0, relativeTo: libraryDir)] } ?? [] + [libraryDir] return [LibraryInfo(libraryPath: libraryFile, headersPaths: headersDirs, moduleMapPath: nil)] } @@ -74,7 +75,8 @@ extension BinaryModule { guard let supportedTriples = $0.supportedTriples else { throw StringError("No \"supportedTriples\" found in the artifact metadata for \(entry.key) in \(self.artifactPath)") } - let filteredSupportedTriples = try supportedTriples + let filteredSupportedTriples = + try supportedTriples .filter { try $0.withoutVersion() == versionLessTriple } return ExecutableInfo( name: entry.key, @@ -89,7 +91,7 @@ extension BinaryModule { // The host triple might contain a version which we don't want to take into account here. let versionLessTriple = try triple.withoutVersion() - return try ArtifactsArchiveMetadata.parse(fileSystem: fileSystem, rootPath: self.artifactPath).artifacts + return try ArtifactsArchiveMetadata.parse(fileSystem: fileSystem, rootPath: self.artifactPath).artifacts .lazy .filter { $0.value.type == .staticLibrary } .flatMap { entry in @@ -98,12 +100,12 @@ extension BinaryModule { .lazy .filter { try ($0.supportedTriples ?? []).contains { try $0.withoutVersion() == versionLessTriple } } .map { - return LibraryInfo( - libraryPath: self.artifactPath.appending($0.path), - headersPaths: $0.staticLibraryMetadata?.headerPaths.map { self.artifactPath.appending($0) } ?? [], - moduleMapPath: $0.staticLibraryMetadata?.moduleMapPath.map { self.artifactPath.appending($0) } - ) - } + return LibraryInfo( + libraryPath: self.artifactPath.appending($0.path), + headersPaths: $0.staticLibraryMetadata?.headerPaths.map { self.artifactPath.appending($0) } ?? [], + moduleMapPath: $0.staticLibraryMetadata?.moduleMapPath.map { self.artifactPath.appending($0) } + ) + } } } } @@ -122,7 +124,7 @@ extension Triple { fileprivate var asXCFrameworkPlatformString: String? { switch self.os { case .darwin, .wasi, .win32, .openbsd, .freebsd, .noneOS: - return nil // XCFrameworks do not support any of these platforms today. + return nil // XCFrameworks do not support any of these platforms today. case .macosx: return "macos" case .ios: @@ -135,9 +137,9 @@ extension Triple { if environment == .android { return nil } - return "linux" // Only if --experimental-xcframeworks-on-linux has been passed + return "linux" // Only if --experimental-xcframeworks-on-linux has been passed default: - return nil // XCFrameworks do not support any of these platforms today. + return nil // XCFrameworks do not support any of these platforms today. } } } @@ -150,7 +152,7 @@ extension Triple.Environment { case .macabi: return "maccatalyst" default: - return nil // XCFrameworks do not support any of these platform variants today. + return nil // XCFrameworks do not support any of these platform variants today. } } } diff --git a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Debugging.swift b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Debugging.swift index a6cc43cdf55..5d5f9f18de3 100644 --- a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Debugging.swift +++ b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Debugging.swift @@ -41,7 +41,7 @@ extension BuildParameters { } public var debugInfoFormat: DebugInfoFormat - + /// Whether the produced executable should be codesigned with the debugging entitlement, enabling enhanced /// backtraces on macOS. public var shouldEnableDebuggingEntitlement: Bool diff --git a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Driver.swift b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Driver.swift index 2201a9e9f20..8f9dfa995f8 100644 --- a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Driver.swift +++ b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Driver.swift @@ -12,7 +12,7 @@ extension BuildParameters { /// A mode for explicit import checking - public enum TargetDependencyImportCheckingMode : Codable { + public enum TargetDependencyImportCheckingMode: Codable { case none case warn case error diff --git a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Linking.swift b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Linking.swift index 6be8baea8c9..a510eafe5cd 100644 --- a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Linking.swift +++ b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Linking.swift @@ -41,7 +41,7 @@ extension BuildParameters { public struct Linking: Encodable { /// Whether to disable dead code stripping by the linker public var linkerDeadStrip: Bool - + public var linkTimeOptimizationMode: LinkTimeOptimizationMode? /// Disables adding $ORIGIN/@loader_path to the rpath, useful when deploying diff --git a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Testing.swift b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Testing.swift index 357c7de25e8..66bd6021b96 100644 --- a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Testing.swift +++ b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Testing.swift @@ -119,9 +119,11 @@ extension BuildParameters { /// The style of test product to produce. public var testProductStyle: TestProductStyle { - return triple.isDarwin() ? .loadableBundle : .entryPointExecutable( - explicitlyEnabledDiscovery: testingParameters.explicitlyEnabledDiscovery, - explicitlySpecifiedPath: testingParameters.explicitlySpecifiedPath - ) + return triple.isDarwin() + ? .loadableBundle + : .entryPointExecutable( + explicitlyEnabledDiscovery: testingParameters.explicitlyEnabledDiscovery, + explicitlySpecifiedPath: testingParameters.explicitlySpecifiedPath + ) } } diff --git a/Sources/SPMBuildCore/BuildParameters/BuildParameters.swift b/Sources/SPMBuildCore/BuildParameters/BuildParameters.swift index e5d9802b79f..a475d0e21af 100644 --- a/Sources/SPMBuildCore/BuildParameters/BuildParameters.swift +++ b/Sources/SPMBuildCore/BuildParameters/BuildParameters.swift @@ -178,17 +178,22 @@ public struct BuildParameters: Encodable { apiDigesterMode: APIDigesterMode? = nil ) throws { // Default to the unversioned triple if none is provided so that we defer to the package's requested deployment target, for Darwin platforms. For other platforms, continue to include the version since those don't have the concept of a package-specified version, and the version is meaningful for some platforms including Android and FreeBSD. - let triple = try triple ?? { - let hostTriple = try Triple.getHostTriple( - usingSwiftCompiler: toolchain.swiftCompilerPath) - return hostTriple.versionedTriple.isDarwin() ? hostTriple.unversionedTriple : hostTriple.versionedTriple - }() - - self.debuggingParameters = debuggingParameters ?? .init( - triple: triple, - shouldEnableDebuggingEntitlement: configuration == .debug, - omitFramePointers: nil - ) + let triple = + try triple + ?? { + let hostTriple = try Triple.getHostTriple( + usingSwiftCompiler: toolchain.swiftCompilerPath + ) + return hostTriple.versionedTriple.isDarwin() ? hostTriple.unversionedTriple : hostTriple.versionedTriple + }() + + self.debuggingParameters = + debuggingParameters + ?? .init( + triple: triple, + shouldEnableDebuggingEntitlement: configuration == .debug, + omitFramePointers: nil + ) self.destination = destination self.dataPath = dataPath @@ -200,30 +205,37 @@ public struct BuildParameters: Encodable { case .dwarf: var flags = flags // DWARF requires lld as link.exe expects CodeView debug info. - self.flags = flags.merging(triple.isWindows() ? BuildFlags( - cCompilerFlags: ["-gdwarf"], - cxxCompilerFlags: ["-gdwarf"], - swiftCompilerFlags: ["-g", "-use-ld=lld"], - linkerFlags: ["-debug:dwarf"] - ) : BuildFlags(cCompilerFlags: ["-g"], cxxCompilerFlags: ["-g"], swiftCompilerFlags: ["-g"])) + self.flags = flags.merging( + triple.isWindows() + ? BuildFlags( + cCompilerFlags: ["-gdwarf"], + cxxCompilerFlags: ["-gdwarf"], + swiftCompilerFlags: ["-g", "-use-ld=lld"], + linkerFlags: ["-debug:dwarf"] + ) : BuildFlags(cCompilerFlags: ["-g"], cxxCompilerFlags: ["-g"], swiftCompilerFlags: ["-g"]) + ) case .codeview: if !triple.isWindows() { throw StringError("CodeView debug information is currently not supported on \(triple.osName)") } var flags = flags - self.flags = flags.merging(BuildFlags( - cCompilerFlags: ["-g"], - cxxCompilerFlags: ["-g"], - swiftCompilerFlags: ["-g", "-debug-info-format=codeview"], - linkerFlags: ["-debug"] - )) + self.flags = flags.merging( + BuildFlags( + cCompilerFlags: ["-g"], + cxxCompilerFlags: ["-g"], + swiftCompilerFlags: ["-g", "-debug-info-format=codeview"], + linkerFlags: ["-debug"] + ) + ) case .none: var flags = flags - self.flags = flags.merging(BuildFlags( - cCompilerFlags: ["-g0"], - cxxCompilerFlags: ["-g0"], - swiftCompilerFlags: ["-gnone"] - )) + self.flags = flags.merging( + BuildFlags( + cCompilerFlags: ["-g0"], + cxxCompilerFlags: ["-g0"], + swiftCompilerFlags: ["-gnone"] + ) + ) } self.pkgConfigDirectories = pkgConfigDirectories self.architectures = architectures @@ -306,9 +318,9 @@ public struct BuildParameters: Encodable { public func macroBinaryPath(_ module: ResolvedModule) throws -> Basics.AbsolutePath { assert(module.type == .macro) #if BUILD_MACROS_AS_DYLIBS - return buildPath.appending(try dynamicLibraryPath(for: module.name)) + return buildPath.appending(try dynamicLibraryPath(for: module.name)) #else - return buildPath.appending(try executablePath(for: module.name)) + return buildPath.appending(try executablePath(for: module.name)) #endif } @@ -357,9 +369,9 @@ public struct BuildParameters: Encodable { } case .macro: #if BUILD_MACROS_AS_DYLIBS - return try dynamicLibraryPath(for: product.name) + return try dynamicLibraryPath(for: product.name) #else - return try executablePath(for: product.name) + return try executablePath(for: product.name) #endif } } diff --git a/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift b/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift index d78d6bb8a2f..dd70e97fc12 100644 --- a/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift +++ b/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift @@ -133,7 +133,7 @@ public struct BuildResult { self.replArguments = replArguments self.builtArtifacts = builtArtifacts } - + public let replArguments: CLIArguments? public let symbolGraph: SymbolGraphResult? public let buildPlan: BuildPlan? diff --git a/Sources/SPMBuildCore/BuildSystem/BuildSystemDelegate.swift b/Sources/SPMBuildCore/BuildSystem/BuildSystemDelegate.swift index 163c16f16e3..6d5ebec47dc 100644 --- a/Sources/SPMBuildCore/BuildSystem/BuildSystemDelegate.swift +++ b/Sources/SPMBuildCore/BuildSystem/BuildSystemDelegate.swift @@ -36,11 +36,11 @@ public protocol BuildSystemDelegate: AnyObject { } public extension BuildSystemDelegate { - func buildSystem(_ buildSystem: BuildSystem, willStartCommand command: BuildSystemCommand) { } - func buildSystem(_ buildSystem: BuildSystem, didStartCommand command: BuildSystemCommand) { } - func buildSystem(_ buildSystem: BuildSystem, didUpdateTaskProgress text: String) { } - func buildSystem(_ buildSystem: BuildSystem, didFinishCommand command: BuildSystemCommand) { } - func buildSystemDidDetectCycleInRules(_ buildSystem: BuildSystem) { } - func buildSystem(_ buildSystem: BuildSystem, didFinishWithResult success: Bool) { } - func buildSystemDidCancel(_ buildSystem: BuildSystem) { } + func buildSystem(_ buildSystem: BuildSystem, willStartCommand command: BuildSystemCommand) {} + func buildSystem(_ buildSystem: BuildSystem, didStartCommand command: BuildSystemCommand) {} + func buildSystem(_ buildSystem: BuildSystem, didUpdateTaskProgress text: String) {} + func buildSystem(_ buildSystem: BuildSystem, didFinishCommand command: BuildSystemCommand) {} + func buildSystemDidDetectCycleInRules(_ buildSystem: BuildSystem) {} + func buildSystem(_ buildSystem: BuildSystem, didFinishWithResult success: Bool) {} + func buildSystemDidCancel(_ buildSystem: BuildSystem) {} } diff --git a/Sources/SPMBuildCore/BuiltTestProduct.swift b/Sources/SPMBuildCore/BuiltTestProduct.swift index 7830caffcaf..9dd1761a6df 100644 --- a/Sources/SPMBuildCore/BuiltTestProduct.swift +++ b/Sources/SPMBuildCore/BuiltTestProduct.swift @@ -38,7 +38,7 @@ public struct BuiltTestProduct: Codable { guard let bundlePath = hierarchySequence.first(where: { $0.basename.hasSuffix(pathExtension) }) else { fatalError("could not find test bundle path from '\(binaryPath)'") } - + return bundlePath } diff --git a/Sources/SPMBuildCore/CommandPluginResult.swift b/Sources/SPMBuildCore/CommandPluginResult.swift index 7efae959d04..3705ae44539 100644 --- a/Sources/SPMBuildCore/CommandPluginResult.swift +++ b/Sources/SPMBuildCore/CommandPluginResult.swift @@ -12,7 +12,8 @@ import Basics -@available(*, +@available( + *, deprecated, renamed: "CommandPluginResult", message: "renamed to unify terminology with the Swift Evolution proposal" @@ -23,7 +24,7 @@ public typealias PrebuildCommandResult = CommandPluginResult public struct CommandPluginResult { /// Paths of any derived files that should be included in the build. public var derivedFiles: [AbsolutePath] - + /// Paths of any directories whose contents influence the build plan. public var outputDirectories: [AbsolutePath] diff --git a/Sources/SPMBuildCore/Plugins/DefaultPluginScriptRunner.swift b/Sources/SPMBuildCore/Plugins/DefaultPluginScriptRunner.swift index a5b450a6f5a..0bfc7bce255 100644 --- a/Sources/SPMBuildCore/Plugins/DefaultPluginScriptRunner.swift +++ b/Sources/SPMBuildCore/Plugins/DefaultPluginScriptRunner.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import Foundation import PackageGraph @@ -24,7 +23,7 @@ import class Basics.AsyncProcess import struct TSCUtility.SerializedDiagnostics #if os(Android) -import Android + import Android #endif /// A plugin script runner that compiles the plugin source files as an executable binary for the host platform, and invokes it as a subprocess. @@ -96,9 +95,9 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { observabilityScope: observabilityScope, callbackQueue: callbackQueue, delegate: delegate, - completion: completion) - } - else { + completion: completion + ) + } else { // Compilation failed, so throw an error. callbackQueue.async { completion(.failure(DefaultPluginScriptRunnerError.compilationFailed(result))) } } @@ -127,9 +126,9 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { // Determine the path of the executable and other produced files. let execName = pluginName.spm_mangledToC99ExtendedIdentifier() #if os(Windows) - let execSuffix = ".exe" + let execSuffix = ".exe" #else - let execSuffix = "" + let execSuffix = "" #endif let execFilePath = self.cacheDir.appending(component: execName + execSuffix) let diagFilePath = self.cacheDir.appending(component: execName + ".dia") @@ -161,31 +160,30 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { "-lPackagePlugin", ] #if !os(Windows) - // -rpath argument is not supported on Windows, - // so we add runtimePath to PATH when executing the manifest instead - commandLine += ["-Xlinker", "-rpath", "-Xlinker", pluginLibraryPath.pathString] + // -rpath argument is not supported on Windows, + // so we add runtimePath to PATH when executing the manifest instead + commandLine += ["-Xlinker", "-rpath", "-Xlinker", pluginLibraryPath.pathString] #endif } #if os(macOS) - // On macOS earlier than 12, add an rpath to the directory that contains the concurrency fallback library. - if #available(macOS 12.0, *) { - // Nothing is needed; the system has everything we need. - } - else { - // Add an `-rpath` so the Swift 5.5 fallback libraries can be found. - let swiftSupportLibPath = self.toolchain.swiftCompilerPathForManifests.parentDirectory.parentDirectory.appending(components: "lib", "swift-5.5", "macosx") - commandLine += ["-Xlinker", "-rpath", "-Xlinker", swiftSupportLibPath.pathString] - } + // On macOS earlier than 12, add an rpath to the directory that contains the concurrency fallback library. + if #available(macOS 12.0, *) { + // Nothing is needed; the system has everything we need. + } else { + // Add an `-rpath` so the Swift 5.5 fallback libraries can be found. + let swiftSupportLibPath = self.toolchain.swiftCompilerPathForManifests.parentDirectory.parentDirectory.appending(components: "lib", "swift-5.5", "macosx") + commandLine += ["-Xlinker", "-rpath", "-Xlinker", swiftSupportLibPath.pathString] + } #endif // Use the same minimum deployment target as the PackagePlugin library (with a fallback to the default host triple). #if os(macOS) - if let version = self.toolchain.swiftPMLibrariesLocation.pluginLibraryMinimumDeploymentTarget?.versionString { - commandLine += ["-target", "\(self.toolchain.targetTriple.tripleString(forPlatformVersion: version))"] - } else { - commandLine += ["-target", self.toolchain.targetTriple.tripleString] - } + if let version = self.toolchain.swiftPMLibrariesLocation.pluginLibraryMinimumDeploymentTarget?.versionString { + commandLine += ["-target", "\(self.toolchain.targetTriple.tripleString(forPlatformVersion: version))"] + } else { + commandLine += ["-target", self.toolchain.targetTriple.tripleString] + } #endif // Add any extra flags required as indicated by the ManifestLoader. @@ -207,9 +205,9 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { commandLine += ["-I", pluginModulesPath.pathString] } #if os(macOS) - if let sdkRoot = self.toolchain.sdkRootPath ?? self.sdkRoot() { - commandLine += ["-sdk", sdkRoot.pathString] - } + if let sdkRoot = self.toolchain.sdkRootPath ?? self.sdkRoot() { + commandLine += ["-sdk", sdkRoot.pathString] + } #endif // Honor any module cache override that's set in the environment. @@ -243,8 +241,7 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { do { observabilityScope.emit(debug: "Plugin compilation output directory '\(execFilePath.parentDirectory)'") try FileManager.default.createDirectory(at: execFilePath.parentDirectory.asURL, withIntermediateDirectories: true, attributes: nil) - } - catch { + } catch { // Bail out right away if we didn't even get this far. return callbackQueue.async { completion(.failure(DefaultPluginScriptRunnerError.compilationPreparationFailed(error: error))) @@ -265,8 +262,7 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { } compilerInputHash = ByteString(encodingAsUTF8: stringToHash).sha256Checksum observabilityScope.emit(debug: "Computed hash of plugin compilation inputs: \(compilerInputHash!)") - } - catch { + } catch { // We couldn't compute the hash. We warn about it but proceed with the compilation (a cache miss). observabilityScope.emit(debug: "Couldn't compute hash of plugin compilation inputs", underlyingError: error) compilerInputHash = .none @@ -289,11 +285,11 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { case .terminated(let code): self = .exit(code: code) #if os(Windows) - case .abnormal(let exception): - self = .abnormal(exception: exception) + case .abnormal(let exception): + self = .abnormal(exception: exception) #else - case .signalled(let signal): - self = .signal(number: signal) + case .signalled(let signal): + self = .signal(number: signal) #endif } } @@ -313,14 +309,14 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { let previousState = try JSONDecoder.makeWithDefaults().decode( path: stateFilePath, fileSystem: fileSystem, - as: PersistedCompilationState.self) + as: PersistedCompilationState.self + ) // If it succeeded last time and the compiler inputs are the same, we don't need to recompile. if previousState.succeeded && previousState.inputHash == compilerInputHash { compilationState = previousState } - } - catch { + } catch { // We couldn't read the compilation state file even though it existed. We warn about it but proceed with recompiling. observabilityScope.emit(debug: "Couldn't read previous compilation state", underlyingError: error) } @@ -335,7 +331,8 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { executableFile: execFilePath, diagnosticsFile: diagFilePath, compilerOutput: compilationState.output, - cached: true) + cached: true + ) delegate.skippedCompilingPlugin(cachedResult: result) return callbackQueue.async { completion(.success(result)) @@ -350,8 +347,7 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { try fileSystem.removeFileTree(execFilePath) try fileSystem.removeFileTree(diagFilePath) try fileSystem.removeFileTree(stateFilePath) - } - catch { + } catch { observabilityScope.emit(debug: "Couldn't clean up before invoking compiler", underlyingError: error) } @@ -359,43 +355,46 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { AsyncProcess.popen(arguments: commandLine, environment: environment, queue: callbackQueue) { // We are now on our caller's requested callback queue, so we just call the completion handler directly. dispatchPrecondition(condition: .onQueue(callbackQueue)) - completion($0.tryMap { process in - // Emit the compiler output as observable info. - let compilerOutput = ((try? process.utf8Output()) ?? "") + ((try? process.utf8stderrOutput()) ?? "") - if !compilerOutput.isEmpty { - observabilityScope.emit(info: compilerOutput) - } + completion( + $0.tryMap { process in + // Emit the compiler output as observable info. + let compilerOutput = ((try? process.utf8Output()) ?? "") + ((try? process.utf8stderrOutput()) ?? "") + if !compilerOutput.isEmpty { + observabilityScope.emit(info: compilerOutput) + } - // Save the persisted compilation state for possible reuse next time. - let compilationState = PersistedCompilationState( - commandLine: commandLine, - environment: toolchain.swiftCompilerEnvironment.cachable, - inputHash: compilerInputHash, - output: compilerOutput, - result: .init(process.exitStatus)) - do { - try JSONEncoder.makeWithDefaults().encode(path: stateFilePath, fileSystem: self.fileSystem, compilationState) - } - catch { - // We couldn't write out the `.state` file. We warn about it but proceed. - observabilityScope.emit(debug: "Couldn't save plugin compilation state", underlyingError: error) - } + // Save the persisted compilation state for possible reuse next time. + let compilationState = PersistedCompilationState( + commandLine: commandLine, + environment: toolchain.swiftCompilerEnvironment.cachable, + inputHash: compilerInputHash, + output: compilerOutput, + result: .init(process.exitStatus) + ) + do { + try JSONEncoder.makeWithDefaults().encode(path: stateFilePath, fileSystem: self.fileSystem, compilationState) + } catch { + // We couldn't write out the `.state` file. We warn about it but proceed. + observabilityScope.emit(debug: "Couldn't save plugin compilation state", underlyingError: error) + } - // Construct a PluginCompilationResult for both the successful and unsuccessful cases (to convey diagnostics, etc). - let result = PluginCompilationResult( - succeeded: compilationState.succeeded, - commandLine: commandLine, - executableFile: execFilePath, - diagnosticsFile: diagFilePath, - compilerOutput: compilerOutput, - cached: false) - - // Tell the delegate that we're done compiling the plugin, passing it the result. - delegate.didCompilePlugin(result: result) - - // Also return the result to the caller. - return result - }) + // Construct a PluginCompilationResult for both the successful and unsuccessful cases (to convey diagnostics, etc). + let result = PluginCompilationResult( + succeeded: compilationState.succeeded, + commandLine: commandLine, + executableFile: execFilePath, + diagnosticsFile: diagFilePath, + compilerOutput: compilerOutput, + cached: false + ) + + // Tell the delegate that we're done compiling the plugin, passing it the result. + delegate.didCompilePlugin(result: result) + + // Also return the result to the caller. + return result + } + ) } } @@ -409,21 +408,24 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { var sdkRootPath: Basics.AbsolutePath? // Find SDKROOT on macOS using xcrun. #if os(macOS) - let foundPath = try? AsyncProcess.checkNonZeroExit( - args: "/usr/bin/xcrun", "--sdk", "macosx", "--show-sdk-path" - ) - guard let sdkRoot = foundPath?.spm_chomp(), !sdkRoot.isEmpty else { - return nil - } - if let path = try? Basics.AbsolutePath(validating: sdkRoot) { - sdkRootPath = path - self.sdkRootCache.put(path) - } + let foundPath = try? AsyncProcess.checkNonZeroExit( + args: "/usr/bin/xcrun", + "--sdk", + "macosx", + "--show-sdk-path" + ) + guard let sdkRoot = foundPath?.spm_chomp(), !sdkRoot.isEmpty else { + return nil + } + if let path = try? Basics.AbsolutePath(validating: sdkRoot) { + sdkRootPath = path + self.sdkRootCache.put(path) + } #endif return sdkRootPath } - + /// Private function that invokes a compiled plugin executable and communicates with it until it finishes. fileprivate func invoke( compiledExec: Basics.AbsolutePath, @@ -437,180 +439,181 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable { delegate: PluginScriptRunnerDelegate, completion: @escaping (Result) -> Void ) { -#if canImport(Darwin) && !os(macOS) - callbackQueue.async { - completion(.failure(DefaultPluginScriptRunnerError.pluginUnavailable(reason: "subprocess invocations are unavailable on this platform"))) - } -#else - // Construct the command line. Currently we just invoke the executable built from the plugin without any parameters. - var command = [compiledExec.pathString] + #if canImport(Darwin) && !os(macOS) + callbackQueue.async { + completion(.failure(DefaultPluginScriptRunnerError.pluginUnavailable(reason: "subprocess invocations are unavailable on this platform"))) + } + #else + // Construct the command line. Currently we just invoke the executable built from the plugin without any parameters. + var command = [compiledExec.pathString] - // Optionally wrap the command in a sandbox, which places some limits on what it can do. In particular, it blocks network access and restricts the paths to which the plugin can make file system changes. It does allow writing to temporary directories. - if self.enableSandbox { - do { - command = try Sandbox.apply( - command: command, - fileSystem: self.fileSystem, - strictness: .writableTemporaryDirectory, - writableDirectories: writableDirectories + [self.cacheDir], - readOnlyDirectories: readOnlyDirectories, - allowNetworkConnections: allowNetworkConnections - ) - } catch { - return callbackQueue.async { - completion(.failure(error)) + // Optionally wrap the command in a sandbox, which places some limits on what it can do. In particular, it blocks network access and restricts the paths to which the plugin can make file system changes. It does allow writing to temporary directories. + if self.enableSandbox { + do { + command = try Sandbox.apply( + command: command, + fileSystem: self.fileSystem, + strictness: .writableTemporaryDirectory, + writableDirectories: writableDirectories + [self.cacheDir], + readOnlyDirectories: readOnlyDirectories, + allowNetworkConnections: allowNetworkConnections + ) + } catch { + return callbackQueue.async { + completion(.failure(error)) + } } } - } - // Create and configure a Process. We set the working directory to the cache directory, so that relative paths end up there. - let process = Foundation.Process() - process.executableURL = URL(fileURLWithPath: command[0]) - process.arguments = Array(command.dropFirst()) - - var env = Environment.current - - // FIXME: This is largely a workaround for improper rpath setup on Linux. It should be - // removed once the Swift Build backend switches to use swiftc as the linker driver - // for targets with Swift sources. For now, limit the scope to non-macOS, so that - // plugins do not inadvertently use the toolchain stdlib instead of the OS stdlib - // when built with a Swift.org toolchain. - #if !os(macOS) - // Update the environment for any runtime library paths that tools compiled - // for the command plugin might require after they have been built. - let runtimeLibPaths = self.toolchain.runtimeLibraryPaths - for libPath in runtimeLibPaths { - env.appendPath(key: .libraryPath, value: libPath.pathString) - } - #endif + // Create and configure a Process. We set the working directory to the cache directory, so that relative paths end up there. + let process = Foundation.Process() + process.executableURL = URL(fileURLWithPath: command[0]) + process.arguments = Array(command.dropFirst()) + + var env = Environment.current + + // FIXME: This is largely a workaround for improper rpath setup on Linux. It should be + // removed once the Swift Build backend switches to use swiftc as the linker driver + // for targets with Swift sources. For now, limit the scope to non-macOS, so that + // plugins do not inadvertently use the toolchain stdlib instead of the OS stdlib + // when built with a Swift.org toolchain. + #if !os(macOS) + // Update the environment for any runtime library paths that tools compiled + // for the command plugin might require after they have been built. + let runtimeLibPaths = self.toolchain.runtimeLibraryPaths + for libPath in runtimeLibPaths { + env.appendPath(key: .libraryPath, value: libPath.pathString) + } + #endif -#if os(Windows) - let pluginLibraryPath = self.toolchain.swiftPMLibrariesLocation.pluginLibraryPath.pathString - env.prependPath(key: .path, value: pluginLibraryPath) -#endif - process.environment = .init(env) - - process.currentDirectoryURL = workingDirectory.asURL - - // Set up a pipe for sending structured messages to the plugin on its stdin. - let stdinPipe = Pipe() - let outputHandle = stdinPipe.fileHandleForWriting - let outputQueue = DispatchQueue(label: "plugin-send-queue") - process.standardInput = stdinPipe - - // Set up a pipe for receiving messages from the plugin on its stdout. - let stdoutPipe = Pipe() - let stdoutLock = NSLock() - stdoutPipe.fileHandleForReading.readabilityHandler = { fileHandle in - // Receive the next message and pass it on to the delegate. - stdoutLock.withLock { - do { - while let message = try fileHandle.readPluginMessage() { - // FIXME: We should handle errors here. - callbackQueue.async { - do { - try delegate.handleMessage(data: message, responder: { data in - outputQueue.async { - do { - try outputHandle.writePluginMessage(data) - } - catch { - print("error while trying to send message to plugin: \(error.interpolationDescription)") + #if os(Windows) + let pluginLibraryPath = self.toolchain.swiftPMLibrariesLocation.pluginLibraryPath.pathString + env.prependPath(key: .path, value: pluginLibraryPath) + #endif + process.environment = .init(env) + + process.currentDirectoryURL = workingDirectory.asURL + + // Set up a pipe for sending structured messages to the plugin on its stdin. + let stdinPipe = Pipe() + let outputHandle = stdinPipe.fileHandleForWriting + let outputQueue = DispatchQueue(label: "plugin-send-queue") + process.standardInput = stdinPipe + + // Set up a pipe for receiving messages from the plugin on its stdout. + let stdoutPipe = Pipe() + let stdoutLock = NSLock() + stdoutPipe.fileHandleForReading.readabilityHandler = { fileHandle in + // Receive the next message and pass it on to the delegate. + stdoutLock.withLock { + do { + while let message = try fileHandle.readPluginMessage() { + // FIXME: We should handle errors here. + callbackQueue.async { + do { + try delegate.handleMessage( + data: message, + responder: { data in + outputQueue.async { + do { + try outputHandle.writePluginMessage(data) + } catch { + print("error while trying to send message to plugin: \(error.interpolationDescription)") + } + } } - } - }) - } - catch DecodingError.keyNotFound(let key, _) where key.stringValue == "version" { - print("message from plugin did not contain a 'version' key, likely an incompatible plugin library is being loaded by the plugin") - } - catch { - print("error while trying to handle message from plugin: \(error.interpolationDescription)") + ) + } catch DecodingError.keyNotFound(let key, _) where key.stringValue == "version" { + print("message from plugin did not contain a 'version' key, likely an incompatible plugin library is being loaded by the plugin") + } catch { + print("error while trying to handle message from plugin: \(error.interpolationDescription)") + } } } + } catch { + print("error while trying to read message from plugin: \(error.interpolationDescription)") } } - catch { - print("error while trying to read message from plugin: \(error.interpolationDescription)") - } } - } - process.standardOutput = stdoutPipe - - // Set up a pipe for receiving free-form text output from the plugin on its stderr. - let stderrPipe = Pipe() - let stderrLock = NSLock() - var stderrData = Data() - let stderrHandler = { (data: Data) in - // Pass on any available data to the delegate. - if data.isEmpty { return } - stderrData.append(contentsOf: data) - callbackQueue.async { delegate.handleOutput(data: data) } - } - stderrPipe.fileHandleForReading.readabilityHandler = { fileHandle in - // Read and pass on any available free-form text output from the plugin. - // We need the lock since we could run concurrently with the termination handler. - stderrLock.withLock { stderrHandler(fileHandle.availableData) } - } - process.standardError = stderrPipe - - // Add it to the list of currently running plugin processes, so it can be cancelled if the host is interrupted. - guard let cancellationKey = self.cancellator.register(process) else { - return callbackQueue.async { - completion(.failure(CancellationError())) + process.standardOutput = stdoutPipe + + // Set up a pipe for receiving free-form text output from the plugin on its stderr. + let stderrPipe = Pipe() + let stderrLock = NSLock() + var stderrData = Data() + let stderrHandler = { (data: Data) in + // Pass on any available data to the delegate. + if data.isEmpty { return } + stderrData.append(contentsOf: data) + callbackQueue.async { delegate.handleOutput(data: data) } } - } + stderrPipe.fileHandleForReading.readabilityHandler = { fileHandle in + // Read and pass on any available free-form text output from the plugin. + // We need the lock since we could run concurrently with the termination handler. + stderrLock.withLock { stderrHandler(fileHandle.availableData) } + } + process.standardError = stderrPipe - // Set up a handler to deal with the exit of the plugin process. - process.terminationHandler = { process in - // Remove the process from the list of currently running ones. - self.cancellator.deregister(cancellationKey) + // Add it to the list of currently running plugin processes, so it can be cancelled if the host is interrupted. + guard let cancellationKey = self.cancellator.register(process) else { + return callbackQueue.async { + completion(.failure(CancellationError())) + } + } - // Close the output handle through which we talked to the plugin. - try? outputHandle.close() + // Set up a handler to deal with the exit of the plugin process. + process.terminationHandler = { process in + // Remove the process from the list of currently running ones. + self.cancellator.deregister(cancellationKey) - // Read and pass on any remaining free-form text output from the plugin. - // We need the lock since we could run concurrently with the readability handler. - stderrLock.withLock { - try? stderrPipe.fileHandleForReading.readToEnd().map{ stderrHandler($0) } - } + // Close the output handle through which we talked to the plugin. + try? outputHandle.close() - // Read and pass on any remaining messages from the plugin. - let handle = stdoutPipe.fileHandleForReading - if let handler = handle.readabilityHandler { - handler(handle) - } + // Read and pass on any remaining free-form text output from the plugin. + // We need the lock since we could run concurrently with the readability handler. + stderrLock.withLock { + try? stderrPipe.fileHandleForReading.readToEnd().map { stderrHandler($0) } + } - // Call the completion block with a result that depends on how the process ended. - callbackQueue.async { - completion(Result { - // We throw an error if the plugin ended with a signal. - if process.terminationReason == .uncaughtSignal { - throw DefaultPluginScriptRunnerError.invocationEndedBySignal( - signal: process.terminationStatus, - command: command, - output: String(decoding: stderrData, as: UTF8.self)) - } - // Otherwise return the termination satatus. - return process.terminationStatus - }) + // Read and pass on any remaining messages from the plugin. + let handle = stdoutPipe.fileHandleForReading + if let handler = handle.readabilityHandler { + handler(handle) + } + + // Call the completion block with a result that depends on how the process ended. + callbackQueue.async { + completion( + Result { + // We throw an error if the plugin ended with a signal. + if process.terminationReason == .uncaughtSignal { + throw DefaultPluginScriptRunnerError.invocationEndedBySignal( + signal: process.terminationStatus, + command: command, + output: String(decoding: stderrData, as: UTF8.self) + ) + } + // Otherwise return the termination satatus. + return process.terminationStatus + } + ) + } } - } - - // Start the plugin process. - do { - try process.run() - } - catch { - callbackQueue.async { - completion(.failure(DefaultPluginScriptRunnerError.invocationFailed(error: error, command: command))) + + // Start the plugin process. + do { + try process.run() + } catch { + callbackQueue.async { + completion(.failure(DefaultPluginScriptRunnerError.invocationFailed(error: error, command: command))) + } } - } - /// Send the initial message to the plugin. - outputQueue.async { - try? outputHandle.writePluginMessage(initialMessage) - } -#endif + /// Send the initial message to the plugin. + outputQueue.async { + try? outputHandle.writePluginMessage(initialMessage) + } + #endif } public func cancel(deadline: DispatchTime) throws { @@ -666,25 +669,25 @@ public enum DefaultPluginScriptRunnerError: Error, CustomStringConvertible { } fileprivate extension FileHandle { - + func writePluginMessage(_ message: Data) throws { // Write the header (a 64-bit length field in little endian byte order). var length = UInt64(littleEndian: UInt64(message.count)) let header = Swift.withUnsafeBytes(of: &length) { Data($0) } assert(header.count == 8) try self.write(contentsOf: header) - + // Write the payload. try self.write(contentsOf: message) } - + func readPluginMessage() throws -> Data? { // Read the header (a 64-bit length field in little endian byte order). guard let header = try self.read(upToCount: 8) else { return nil } guard header.count == 8 else { throw PluginMessageError.truncatedHeader } - let length = header.withUnsafeBytes{ $0.loadUnaligned(as: UInt64.self).littleEndian } + let length = header.withUnsafeBytes { $0.loadUnaligned(as: UInt64.self).littleEndian } guard length >= 2 else { throw PluginMessageError.invalidPayloadSize } diff --git a/Sources/SPMBuildCore/Plugins/PluginContextSerializer.swift b/Sources/SPMBuildCore/Plugins/PluginContextSerializer.swift index 83b3b90321d..691d7313f97 100644 --- a/Sources/SPMBuildCore/Plugins/PluginContextSerializer.swift +++ b/Sources/SPMBuildCore/Plugins/PluginContextSerializer.swift @@ -41,32 +41,32 @@ internal struct PluginContextSerializer { var xcodeTargetsToIds: [XcodeProjectRepresentation.Target: WireInput.XcodeTarget.Id] = [:] var xcodeProjects: [WireInput.XcodeProject] = [] var xcodeProjectsToIds: [XcodeProjectRepresentation: WireInput.XcodeProject.Id] = [:] - + /// Adds a path to the serialized structure, if it isn't already there. /// Either way, this function returns the path's wire ID. mutating func serialize(path: Basics.AbsolutePath) throws -> WireInput.URL.Id { // If we've already seen the path, just return the wire ID we already assigned to it. if let id = pathsToIds[path] { return id } - + // Split up the path into a base path and a subpath (currently always with the last path component as the // subpath, but this can be optimized where there are sequences of path components with a valence of one). let basePathId: Int? if path.parentDirectory.isRoot { // Windows does not have a single root path like UNIX, so capture the root path itself such that we can rejoin it later #if os(Windows) - let id = paths.count - paths.append(.init(baseURLId: nil, subpath: path.parentDirectory.pathString)) - pathsToIds[path] = id - basePathId = id + let id = paths.count + paths.append(.init(baseURLId: nil, subpath: path.parentDirectory.pathString)) + pathsToIds[path] = id + basePathId = id #else - basePathId = nil + basePathId = nil #endif } else { basePathId = try serialize(path: path.parentDirectory) } let subpathString = path.basename - + // Finally assign the next wire ID to the path, and append a serialized Path record. let id = paths.count paths.append(.init(baseURLId: basePathId, subpath: subpathString)) @@ -83,22 +83,30 @@ internal struct PluginContextSerializer { // Construct the FileList var targetFiles: [WireInput.File] = [] - targetFiles.append(contentsOf: try target.underlying.sources.paths.map { - .init(basePathId: try serialize(path: $0.parentDirectory), name: $0.basename, type: .source) - }) - targetFiles.append(contentsOf: try target.underlying.resources.map { - .init(basePathId: try serialize(path: $0.path.parentDirectory), name: $0.path.basename, type: .resource) - }) - targetFiles.append(contentsOf: try target.underlying.ignored.map { - .init(basePathId: try serialize(path: $0.parentDirectory), name: $0.basename, type: .unknown) - }) - targetFiles.append(contentsOf: try target.underlying.others.map { - .init(basePathId: try serialize(path: $0.parentDirectory), name: $0.basename, type: .unknown) - }) - + targetFiles.append( + contentsOf: try target.underlying.sources.paths.map { + .init(basePathId: try serialize(path: $0.parentDirectory), name: $0.basename, type: .source) + } + ) + targetFiles.append( + contentsOf: try target.underlying.resources.map { + .init(basePathId: try serialize(path: $0.path.parentDirectory), name: $0.path.basename, type: .resource) + } + ) + targetFiles.append( + contentsOf: try target.underlying.ignored.map { + .init(basePathId: try serialize(path: $0.parentDirectory), name: $0.basename, type: .unknown) + } + ) + targetFiles.append( + contentsOf: try target.underlying.others.map { + .init(basePathId: try serialize(path: $0.parentDirectory), name: $0.basename, type: .unknown) + } + ) + // Create a scope for evaluating build settings. let scope = BuildSettings.Scope(target.underlying.buildSettings, environment: buildEnvironment) - + // Look at the target and decide what to serialize. At this point we may decide to not serialize it at all. let targetInfo: WireInput.Target.TargetInfo switch target.underlying { @@ -109,7 +117,8 @@ internal struct PluginContextSerializer { sourceFiles: targetFiles, compilationConditions: scope.evaluate(.SWIFT_ACTIVE_COMPILATION_CONDITIONS), linkedLibraries: scope.evaluate(.LINK_LIBRARIES), - linkedFrameworks: scope.evaluate(.LINK_FRAMEWORKS)) + linkedFrameworks: scope.evaluate(.LINK_FRAMEWORKS) + ) case let target as ClangModule: targetInfo = .clangSourceModuleInfo( @@ -120,7 +129,8 @@ internal struct PluginContextSerializer { headerSearchPaths: scope.evaluate(.HEADER_SEARCH_PATHS), publicHeadersDirId: try serialize(path: target.includeDir), linkedLibraries: scope.evaluate(.LINK_LIBRARIES), - linkedFrameworks: scope.evaluate(.LINK_FRAMEWORKS)) + linkedFrameworks: scope.evaluate(.LINK_FRAMEWORKS) + ) case let target as SystemLibraryModule: var cFlags: [String] = [] @@ -139,8 +149,7 @@ internal struct PluginContextSerializer { warning: "\(error.interpolationDescription)", metadata: .pkgConfig(pcFile: result.pkgConfigName, targetName: target.name) ) - } - else { + } else { cFlags += result.cFlags ldFlags += result.libs } @@ -149,8 +158,9 @@ internal struct PluginContextSerializer { targetInfo = .systemLibraryInfo( pkgConfig: target.pkgConfig, compilerFlags: cFlags, - linkerFlags: ldFlags) - + linkerFlags: ldFlags + ) + case let target as BinaryModule: let artifactKind: WireInput.Target.TargetInfo.BinaryArtifactKind switch target.kind { @@ -172,13 +182,14 @@ internal struct PluginContextSerializer { targetInfo = .binaryArtifactInfo( kind: artifactKind, origin: artifactOrigin, - artifactId: try serialize(path: target.artifactPath)) - + artifactId: try serialize(path: target.artifactPath) + ) + default: // It's not a type of target that we pass through to the plugin. return nil } - + // We only get this far if we are serializing the target. If so we also serialize its dependencies. This needs to be done before assigning the next wire ID for the target we're serializing, to make sure we end up with the correct one. let dependencies: [WireInput.Target.Dependency] = try target.dependencies(satisfying: buildEnvironment).compactMap { switch $0 { @@ -191,11 +202,14 @@ internal struct PluginContextSerializer { // Finally assign the next wire ID to the target, and append a serialized Target record. let id = targets.count - targets.append(.init( - name: target.name, - directoryId: try serialize(path: target.sources.root), - dependencies: dependencies, - info: targetInfo)) + targets.append( + .init( + name: target.name, + directoryId: try serialize(path: target.sources.root), + dependencies: dependencies, + info: targetInfo + ) + ) targetsToWireIDs[target.id] = id return id } @@ -210,7 +224,7 @@ internal struct PluginContextSerializer { // Look at the product and decide what to serialize. At this point we may decide to not serialize it at all. let productInfo: WireInput.Product.ProductInfo switch product.type { - + case .executable: let mainExecTarget = try product.executableModule guard let mainExecTargetId = try serialize(target: mainExecTarget) else { @@ -232,13 +246,16 @@ internal struct PluginContextSerializer { // It's not a type of product that we pass through to the plugin. return nil } - + // Finally assign the next wire ID to the product, and append a serialized Product record. let id = products.count - products.append(.init( - name: product.name, - targetIds: try product.modules.compactMap{ try serialize(target: $0) }, - info: productInfo)) + products.append( + .init( + name: product.name, + targetIds: try product.modules.compactMap { try serialize(target: $0) }, + info: productInfo + ) + ) productsToWireIDs[product.id] = id return id } @@ -272,18 +289,22 @@ internal struct PluginContextSerializer { // Assign the next wire ID to the package, and append a serialized Package record. let id = packages.count - packages.append(.init( - identity: package.identity.description, - displayName: package.manifest.displayName, - directoryId: try serialize(path: package.path), - origin: try origin(for: package), - toolsVersion: .init( - major: package.manifest.toolsVersion.major, - minor: package.manifest.toolsVersion.minor, - patch: package.manifest.toolsVersion.patch), - dependencies: dependencies, - productIds: try package.products.compactMap{ try serialize(product: $0) }, - targetIds: try package.modules.compactMap{ try serialize(target: $0) })) + packages.append( + .init( + identity: package.identity.description, + displayName: package.manifest.displayName, + directoryId: try serialize(path: package.path), + origin: try origin(for: package), + toolsVersion: .init( + major: package.manifest.toolsVersion.major, + minor: package.manifest.toolsVersion.minor, + patch: package.manifest.toolsVersion.patch + ), + dependencies: dependencies, + productIds: try package.products.compactMap { try serialize(product: $0) }, + targetIds: try package.modules.compactMap { try serialize(target: $0) } + ) + ) packagesToWireIDs[package.id] = id return id } @@ -295,22 +316,26 @@ internal struct PluginContextSerializer { // Create the list of source files. var inputFiles: [WireInput.File] = [] - inputFiles.append(contentsOf: try xcodeTarget.inputFiles.map { - .init(basePathId: try serialize(path: $0.path.parentDirectory), name: $0.path.basename, type: .init($0.role)) - }) + inputFiles.append( + contentsOf: try xcodeTarget.inputFiles.map { + .init(basePathId: try serialize(path: $0.path.parentDirectory), name: $0.path.basename, type: .init($0.role)) + } + ) // Assign the next wire ID to the target, and append a serialized XcodeProject record. let id = xcodeTargets.count - xcodeTargets.append(.init( - displayName: xcodeTarget.displayName, - product: xcodeTarget.product.map{ .init(name: $0.name, kind: .init($0.kind)) }, - dependencies: [], - inputFiles: inputFiles)) + xcodeTargets.append( + .init( + displayName: xcodeTarget.displayName, + product: xcodeTarget.product.map { .init(name: $0.name, kind: .init($0.kind)) }, + dependencies: [], + inputFiles: inputFiles + ) + ) xcodeTargetsToIds[xcodeTarget] = id return id } - // Adds an Xcode project to the serialized structure, if it isn't already there. // Either way, this function returns the project's wire ID. mutating func serialize(xcodeProject: XcodeProjectRepresentation) throws -> WireInput.XcodeProject.Id { @@ -319,12 +344,15 @@ internal struct PluginContextSerializer { // Assign the next wire ID to the project, and append a serialized XcodeProject record. let id = xcodeProjects.count - xcodeProjects.append(.init( - displayName: xcodeProject.displayName, - directoryPathId: try serialize(path: xcodeProject.directoryPath), - dependencies: [], - urlIds: try xcodeProject.filePaths.map { try serialize(path: $0) }, - targetIds: try xcodeProject.targets.compactMap{ try serialize(xcodeTarget: $0) })) + xcodeProjects.append( + .init( + displayName: xcodeProject.displayName, + directoryPathId: try serialize(path: xcodeProject.directoryPath), + dependencies: [], + urlIds: try xcodeProject.filePaths.map { try serialize(path: $0) }, + targetIds: try xcodeProject.targets.compactMap { try serialize(xcodeTarget: $0) } + ) + ) xcodeProjectsToIds[xcodeProject] = id return id } diff --git a/Sources/SPMBuildCore/Plugins/PluginInvocation.swift b/Sources/SPMBuildCore/Plugins/PluginInvocation.swift index 200727c6990..57bc1b25194 100644 --- a/Sources/SPMBuildCore/Plugins/PluginInvocation.swift +++ b/Sources/SPMBuildCore/Plugins/PluginInvocation.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import _Concurrency import Foundation @@ -152,8 +151,7 @@ extension PluginModule { // Create the plugin's output directory if needed (but don't do anything with it if it already exists). do { try fileSystem.createDirectory(outputDirectory, recursive: true) - } - catch { + } catch { return callbackQueue.async { completion(.failure(PluginEvaluationError.couldNotCreateOuputDirectory(path: outputDirectory, underlyingError: error))) } } @@ -168,7 +166,7 @@ extension PluginModule { sdkRootPath: sdkRootPath ) let pluginWorkDirId = try serializer.serialize(path: outputDirectory) - let toolSearchDirIds = try toolSearchDirectories.map{ try serializer.serialize(path: $0) } + let toolSearchDirIds = try toolSearchDirectories.map { try serializer.serialize(path: $0) } let accessibleTools = try accessibleTools.mapValues { (tool) -> HostToPluginMessage.InputContext.Tool in let path = try serializer.serialize(path: tool.path) return .init(path: path, triples: tool.triples) @@ -192,7 +190,8 @@ extension PluginModule { xcodeProjects: serializer.xcodeProjects, pluginWorkDirId: pluginWorkDirId, toolSearchDirIds: toolSearchDirIds, - accessibleTools: accessibleTools) + accessibleTools: accessibleTools + ) actionMessage = .createBuildToolCommands( context: wireInput, rootPackageId: rootPackageId, @@ -217,7 +216,8 @@ extension PluginModule { xcodeProjects: serializer.xcodeProjects, pluginWorkDirId: pluginWorkDirId, toolSearchDirIds: toolSearchDirIds, - accessibleTools: accessibleTools) + accessibleTools: accessibleTools + ) actionMessage = .createXcodeProjectBuildToolCommands( context: wireInput, rootProjectId: rootProjectId, @@ -237,12 +237,14 @@ extension PluginModule { xcodeProjects: serializer.xcodeProjects, pluginWorkDirId: pluginWorkDirId, toolSearchDirIds: toolSearchDirIds, - accessibleTools: accessibleTools) + accessibleTools: accessibleTools + ) actionMessage = .performCommand( context: wireInput, rootPackageId: rootPackageId, - arguments: arguments) - + arguments: arguments + ) + case .performXcodeProjectCommand(let xcodeProject, let arguments): let rootProjectId = try serializer.serialize(xcodeProject: xcodeProject) let wireInput = WireInput( @@ -254,15 +256,16 @@ extension PluginModule { xcodeProjects: serializer.xcodeProjects, pluginWorkDirId: pluginWorkDirId, toolSearchDirIds: toolSearchDirIds, - accessibleTools: accessibleTools) + accessibleTools: accessibleTools + ) actionMessage = .performXcodeProjectCommand( context: wireInput, rootProjectId: rootProjectId, - arguments: arguments) + arguments: arguments + ) } initialMessage = try actionMessage.toData() - } - catch { + } catch { return callbackQueue.async { completion(.failure(PluginEvaluationError.couldNotSerializePluginInput(underlyingError: error))) } } @@ -338,9 +341,10 @@ extension PluginModule { executable: try config.executable.filePath, arguments: config.arguments, environment: config.environment, - workingDirectory: try config.workingDirectory.map{ try $0.filePath }, - inputFiles: try inputFiles.map{ try $0.filePath }, - outputFiles: try outputFiles.map{ try $0.filePath }) + workingDirectory: try config.workingDirectory.map { try $0.filePath }, + inputFiles: try inputFiles.map { try $0.filePath }, + outputFiles: try outputFiles.map { try $0.filePath } + ) case .definePrebuildCommand(let config, let outputFilesDir): if config.version != 2 { @@ -351,8 +355,9 @@ extension PluginModule { executable: try config.executable.filePath, arguments: config.arguments, environment: config.environment, - workingDirectory: try config.workingDirectory.map{ try $0.filePath }, - outputFilesDirectory: try outputFilesDir.filePath) + workingDirectory: try config.workingDirectory.map { try $0.filePath }, + outputFilesDirectory: try outputFilesDir.filePath + ) if !success { exitEarly = true @@ -368,8 +373,7 @@ extension PluginModule { case .failure(let error): responder(try HostToPluginMessage.errorResponse(error: String(describing: error)).toData()) } - } - catch { + } catch { self.observabilityScope.emit(debug: "couldn't send reply to plugin", underlyingError: error) } } @@ -383,8 +387,7 @@ extension PluginModule { case .failure(let error): responder(try HostToPluginMessage.errorResponse(error: String(describing: error)).toData()) } - } - catch { + } catch { self.observabilityScope.emit(debug: "couldn't send reply to plugin", underlyingError: error) } } @@ -399,8 +402,7 @@ extension PluginModule { case .failure(let error): responder(try HostToPluginMessage.errorResponse(error: String(describing: error)).toData()) } - } - catch { + } catch { self.observabilityScope.emit(debug: "couldn't send reply to plugin", underlyingError: error) } } @@ -422,9 +424,11 @@ extension PluginModule { fileSystem: fileSystem, observabilityScope: observabilityScope, callbackQueue: callbackQueue, - delegate: runnerDelegate) { result in - dispatchPrecondition(condition: .onQueue(callbackQueue)) - completion(result.map { exitCode in + delegate: runnerDelegate + ) { result in + dispatchPrecondition(condition: .onQueue(callbackQueue)) + completion( + result.map { exitCode in // Return a result based on the exit code or the `exitEarly` parameter. If the plugin // exits with an error but hasn't already emitted an error, we do so for it. let exitedCleanly = (exitCode == 0) && !runnerDelegate.exitEarly @@ -434,7 +438,8 @@ extension PluginModule { ) } return exitedCleanly - }) + } + ) } } @@ -516,7 +521,7 @@ extension PluginModule { // Determine additional input dependencies for any plugin commands, // based on any executables the plugin target depends on. let toolPaths = accessibleTools.values.map(\.path).sorted() - + let builtToolPaths = accessibleTools.values.filter({ $0.source == .built }).map((\.path)).sorted() let delegate = DefaultPluginInvocationDelegate( @@ -549,12 +554,13 @@ extension PluginModule { completion: { let duration = startTime.distance(to: .now()) - let success: Bool = switch $0 { - case .success(let result): - result - case .failure: - false - } + let success: Bool = + switch $0 { + case .success(let result): + result + case .failure: + false + } let invocationResult = BuildToolPluginInvocationResult( plugin: self, @@ -649,7 +655,6 @@ extension ModulesGraph { } } - /// A description of a tool to which a plugin has access. public enum PluginAccessibleTool: Hashable { /// A tool that is built by an ExecutableTarget (the path is relative to the built-products directory). @@ -667,42 +672,43 @@ fileprivate func collectAccessibleTools( for hostTriple: Triple ) throws -> Set { precondition(plugin.underlying is PluginModule) - return try Set(plugin.dependencies(satisfying: environment).flatMap { dependency -> [PluginAccessibleTool] in - let builtToolName: String - let executableOrBinaryModule: Module - switch dependency { - case .module(let module, _): - builtToolName = module.name - executableOrBinaryModule = module.underlying - case .product(let product, _): - guard let executableModule = product.modules.map({ $0.underlying }).executables.spm_only - else { - throw StringError("no product named \(product.name)") + return try Set( + plugin.dependencies(satisfying: environment).flatMap { dependency -> [PluginAccessibleTool] in + let builtToolName: String + let executableOrBinaryModule: Module + switch dependency { + case .module(let module, _): + builtToolName = module.name + executableOrBinaryModule = module.underlying + case .product(let product, _): + guard let executableModule = product.modules.map({ $0.underlying }).executables.spm_only + else { + throw StringError("no product named \(product.name)") + } + builtToolName = product.name + executableOrBinaryModule = executableModule } - builtToolName = product.name - executableOrBinaryModule = executableModule - } - // For a binary target we create a `vendedTool`. - if let module = executableOrBinaryModule as? BinaryModule { - // TODO: Memoize this result for the host triple - let execInfos = try module.parseExecutableArtifactArchives(for: hostTriple, fileSystem: fileSystem) - return try execInfos.map { - .vendedTool( - name: $0.name, - path: $0.executablePath, - supportedTriples: try $0.supportedTriples.map { try $0.withoutVersion().tripleString } - ) + // For a binary target we create a `vendedTool`. + if let module = executableOrBinaryModule as? BinaryModule { + // TODO: Memoize this result for the host triple + let execInfos = try module.parseExecutableArtifactArchives(for: hostTriple, fileSystem: fileSystem) + return try execInfos.map { + .vendedTool( + name: $0.name, + path: $0.executablePath, + supportedTriples: try $0.supportedTriples.map { try $0.withoutVersion().tripleString } + ) + } + } + // For an executable target we create a `builtTool`. + else if executableOrBinaryModule.type == .executable { + return try [.builtTool(name: builtToolName, path: RelativePath(validating: executableOrBinaryModule.name))] + } else { + return [] } } - // For an executable target we create a `builtTool`. - else if executableOrBinaryModule.type == .executable { - return try [.builtTool(name: builtToolName, path: RelativePath(validating: executableOrBinaryModule.name))] - } - else { - return [] - } - }) + ) } public extension ResolvedModule { @@ -807,7 +813,6 @@ public struct BuildToolPluginInvocationResult { } } - /// An error in plugin evaluation. public enum PluginEvaluationError: Swift.Error { case couldNotFindPackage(for: PluginModule) @@ -903,17 +908,19 @@ final class DefaultPluginInvocationDelegate: PluginInvocationDelegate { outputFiles: [AbsolutePath] ) { dispatchPrecondition(condition: .onQueue(self.delegateQueue)) - self.buildCommands.append(.init( - configuration: .init( - displayName: displayName, - executable: executable, - arguments: arguments, - environment: .init(environment), - workingDirectory: workingDirectory - ), - inputFiles: self.toolPaths + inputFiles, - outputFiles: outputFiles - )) + self.buildCommands.append( + .init( + configuration: .init( + displayName: displayName, + executable: executable, + arguments: arguments, + environment: .init(environment), + workingDirectory: workingDirectory + ), + inputFiles: self.toolPaths + inputFiles, + outputFiles: outputFiles + ) + ) } func pluginDefinedPrebuildCommand( @@ -935,16 +942,18 @@ final class DefaultPluginInvocationDelegate: PluginInvocationDelegate { ) return false } - self.prebuildCommands.append(.init( - configuration: .init( - displayName: displayName, - executable: executable, - arguments: arguments, - environment: .init(environment), - workingDirectory: workingDirectory - ), - outputFilesDirectory: outputFilesDirectory - )) + self.prebuildCommands.append( + .init( + configuration: .init( + displayName: displayName, + executable: executable, + arguments: arguments, + environment: .init(environment), + workingDirectory: workingDirectory + ), + outputFilesDirectory: outputFilesDirectory + ) + ) return true } } @@ -1177,22 +1186,22 @@ fileprivate extension PluginInvocationTestParameters { fileprivate extension HostToPluginMessage.TestResult { init(_ result: PluginInvocationTestResult) { self.succeeded = result.succeeded - self.testTargets = result.testTargets.map{ .init($0) } - self.codeCoverageDataFile = result.codeCoverageDataFile.map{ .init($0) } + self.testTargets = result.testTargets.map { .init($0) } + self.codeCoverageDataFile = result.codeCoverageDataFile.map { .init($0) } } } fileprivate extension HostToPluginMessage.TestResult.TestTarget { init(_ testTarget: PluginInvocationTestResult.TestTarget) { self.name = testTarget.name - self.testCases = testTarget.testCases.map{ .init($0) } + self.testCases = testTarget.testCases.map { .init($0) } } } fileprivate extension HostToPluginMessage.TestResult.TestTarget.TestCase { init(_ testCase: PluginInvocationTestResult.TestTarget.TestCase) { self.name = testCase.name - self.tests = testCase.tests.map{ .init($0) } + self.tests = testCase.tests.map { .init($0) } } } diff --git a/Sources/SPMBuildCore/Plugins/PluginScriptRunner.swift b/Sources/SPMBuildCore/Plugins/PluginScriptRunner.swift index fda28b919a0..9ab621cf7d3 100644 --- a/Sources/SPMBuildCore/Plugins/PluginScriptRunner.swift +++ b/Sources/SPMBuildCore/Plugins/PluginScriptRunner.swift @@ -21,7 +21,7 @@ import TSCUtility /// Implements the mechanics of running and communicating with a plugin (implemented as a set of Swift source files). In most environments this is done by compiling the code to an executable, invoking it as a sandboxed subprocess, and communicating with it using pipes. Specific implementations are free to implement things differently, however. public protocol PluginScriptRunner { - + /// Public protocol function that starts compiling the plugin script to an executable. The name is used as the basename for the executable and auxiliary files. The tools version controls the availability of APIs in PackagePlugin, and should be set to the tools version of the package that defines the plugin (not of the target to which it is being applied). This function returns immediately and then calls the completion handler on the callback queue when compilation ends. @available(*, noasync, message: "Use the async alternative") func compilePluginScript( @@ -83,7 +83,7 @@ public extension PluginScriptRunner { callbackQueue: callbackQueue, delegate: delegate, completion: { - continuation.resume(with: $0) + continuation.resume(with: $0) } ) } @@ -97,7 +97,7 @@ public protocol PluginScriptCompilerDelegate { /// Called immediately after compiling a plugin (regardless of whether it succeeded or failed). Will not be called if the plugin didn't have to be compiled. This call is always follows a `willCompilePlugin()` but is mutually exclusive with a `skippedCompilingPlugin()` call. func didCompilePlugin(result: PluginCompilationResult) - + /// Called if a plugin didn't need to be compiled because previous compilation results were still valid. In this case neither `willCompilePlugin()` nor `didCompilePlugin()` will be called. func skippedCompilingPlugin(cachedResult: PluginCompilationResult) } @@ -106,7 +106,7 @@ public protocol PluginScriptCompilerDelegate { public protocol PluginScriptRunnerDelegate { /// Called for each piece of textual output data emitted by the plugin. Note that there is no guarantee that the data begins and ends on a UTF-8 byte sequence boundary (much less on a line boundary) so the delegate should buffer partial data as appropriate. func handleOutput(data: Data) - + /// Called for each length-delimited message received from the plugin. The `responder` is closure that can be used to send one or more messages in reply. func handleMessage(data: Data, responder: @escaping (Data) -> Void) throws } @@ -115,22 +115,22 @@ public protocol PluginScriptRunnerDelegate { public struct PluginCompilationResult: Equatable { /// Whether compilation succeeded. public var succeeded: Bool - + /// Complete compiler command line. public var commandLine: [String] - + /// Path of the compiled executable. public var executableFile: Basics.AbsolutePath /// Path of the libClang diagnostics file emitted by the compiler. public var diagnosticsFile: Basics.AbsolutePath - + /// Any output emitted by the compiler (stdout and stderr combined). public var rawCompilerOutput: String - + /// Whether the compilation result came from the cache (false means that the compiler did run). public var cached: Bool - + public init( succeeded: Bool, commandLine: [String], diff --git a/Sources/SPMBuildCore/XcodeProjectRepresentation.swift b/Sources/SPMBuildCore/XcodeProjectRepresentation.swift index 5fb066ac535..bd21f2443f6 100644 --- a/Sources/SPMBuildCore/XcodeProjectRepresentation.swift +++ b/Sources/SPMBuildCore/XcodeProjectRepresentation.swift @@ -16,19 +16,19 @@ public struct XcodeProjectRepresentation: Equatable, Hashable { public var directoryPath: AbsolutePath public var filePaths: [AbsolutePath] public var targets: [Target] - + public init(displayName: String, directoryPath: AbsolutePath, filePaths: [AbsolutePath], targets: [Target]) { self.displayName = displayName self.directoryPath = directoryPath self.filePaths = filePaths self.targets = targets } - + public struct Target: Equatable, Hashable { public var displayName: String public var product: Product? public var inputFiles: [InputFile] - + public init(displayName: String, product: Product?, inputFiles: [InputFile]) { self.displayName = displayName self.product = product @@ -38,7 +38,7 @@ public struct XcodeProjectRepresentation: Equatable, Hashable { public struct Product: Equatable, Hashable { public var name: String public var kind: Kind - + public init(name: String, kind: Kind) { self.name = name self.kind = kind @@ -57,7 +57,7 @@ public struct XcodeProjectRepresentation: Equatable, Hashable { public struct InputFile: Equatable, Hashable { public var path: AbsolutePath public var role: Role - + public init(path: AbsolutePath, role: Role) { self.path = path self.role = role diff --git a/Sources/SPMLLBuild/llbuild.swift b/Sources/SPMLLBuild/llbuild.swift index 8f2622af349..2bbe6483d7e 100644 --- a/Sources/SPMLLBuild/llbuild.swift +++ b/Sources/SPMLLBuild/llbuild.swift @@ -12,10 +12,10 @@ // We either export the llbuildSwift shared library or the llbuild framework. #if canImport(llbuildSwift) -@_exported import llbuildSwift -@_exported import llbuild + @_exported import llbuildSwift + @_exported import llbuild #else -@_exported import llbuild + @_exported import llbuild #endif import Basics @@ -62,7 +62,9 @@ public final class LLBuildEngine { func lookupRule(_ key: Key) -> Rule { let ruleKey = try! RuleKey(key) return delegate.lookupRule( - rule: ruleKey.rule, key: Key(ruleKey.data)) + rule: ruleKey.rule, + key: Key(ruleKey.data) + ) } func error(_ message: String) { @@ -87,7 +89,9 @@ public final class LLBuildEngine { delegate.errors.removeAll() let encodedKey = try RuleKey( - rule: T.BuildRule.ruleName, data: try key.toKey().data).toKey() + rule: T.BuildRule.ruleName, + data: try key.toKey().data + ).toKey() let value = engine.build(key: encodedKey) // Throw if the engine encountered any fatal error during the build. @@ -118,7 +122,9 @@ public class LLTaskBuildEngine { public func taskNeedsInput(_ key: T, inputID: Int) throws { let encodedKey = try RuleKey( - rule: T.BuildRule.ruleName, data: try key.toKey().data).toKey() + rule: T.BuildRule.ruleName, + data: try key.toKey().data + ).toKey() engine.taskNeedsInput(encodedKey, inputID: inputID) } diff --git a/Sources/SourceControl/GitRepository.swift b/Sources/SourceControl/GitRepository.swift index 6dbdf063275..91f570006cb 100644 --- a/Sources/SourceControl/GitRepository.swift +++ b/Sources/SourceControl/GitRepository.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(ProcessEnvironmentBlockShim) -import Basics +@_spi(ProcessEnvironmentBlockShim) import Basics import Dispatch import class Foundation.NSLock @@ -55,7 +54,7 @@ private struct GitShellHelper { let result: AsyncProcessResult do { guard let terminationKey = self.cancellator.register(process) else { - throw CancellationError() // terminating + throw CancellationError() // terminating } defer { self.cancellator.deregister(terminationKey) } try process.launch() @@ -109,10 +108,13 @@ public struct GitRepositoryProvider: RepositoryProvider, Cancellable { do { // Capture stdout and stderr from the Git subprocess invocation, but also pass along stderr to the // handler. We count on it being line-buffered. - let outputHandler = AsyncProcess.OutputRedirection.stream(stdout: { stdoutBytes += $0 }, stderr: { - stderrBytes += $0 - gitFetchStatusFilter($0, progress: progress) - }) + let outputHandler = AsyncProcess.OutputRedirection.stream( + stdout: { stdoutBytes += $0 }, + stderr: { + stderrBytes += $0 + gitFetchStatusFilter($0, progress: progress) + } + ) return try self.git.run( args + ["--progress"], environment: environment, @@ -161,16 +163,17 @@ public struct GitRepositoryProvider: RepositoryProvider, Cancellable { _ options: [String], progress: FetchProgress.Handler? = nil ) throws { - let invocation: [String] = [ - "clone", - // Enable symbolic links for Windows support. - "-c", "core.symlinks=true", - // Disable fsmonitor to avoid spawning a monitor process. - "-c", "core.fsmonitor=false", - // Enable long path support on Windows as otherwise we are limited - // to 261 characters in the complete path. - "-c", "core.longpaths=true", - ] + options + [origin, destination] + let invocation: [String] = + [ + "clone", + // Enable symbolic links for Windows support. + "-c", "core.symlinks=true", + // Disable fsmonitor to avoid spawning a monitor process. + "-c", "core.fsmonitor=false", + // Enable long path support on Windows as otherwise we are limited + // to 261 characters in the complete path. + "-c", "core.longpaths=true", + ] + options + [origin, destination] try self.callGit( invocation, @@ -322,8 +325,8 @@ public final class GitRepository: Repository, WorkingCheckout { } for byte in bytes { switch byte { - case UInt8(ascii: "0") ... UInt8(ascii: "9"), - UInt8(ascii: "a") ... UInt8(ascii: "z"): + case UInt8(ascii: "0")...UInt8(ascii: "9"), + UInt8(ascii: "a")...UInt8(ascii: "z"): continue default: return nil @@ -426,10 +429,12 @@ public final class GitRepository: Repository, WorkingCheckout { self.git = git self.path = path self.isWorkingRepo = isWorkingRepo - assert({ - // Ignore if we couldn't run popen for some reason. - (try? self.isBare() != isWorkingRepo) ?? true - }()) + assert( + { + // Ignore if we couldn't run popen for some reason. + (try? self.isBare() != isWorkingRepo) ?? true + }() + ) } /// Private function to invoke the Git tool with its default environment and given set of arguments, specifying the @@ -447,10 +452,13 @@ public final class GitRepository: Repository, WorkingCheckout { do { // Capture stdout and stderr from the Git subprocess invocation, but also pass along stderr to the // handler. We count on it being line-buffered. - let outputHandler = AsyncProcess.OutputRedirection.stream(stdout: { stdoutBytes += $0 }, stderr: { - stderrBytes += $0 - gitFetchStatusFilter($0, progress: progress) - }) + let outputHandler = AsyncProcess.OutputRedirection.stream( + stdout: { stdoutBytes += $0 }, + stderr: { + stderrBytes += $0 + gitFetchStatusFilter($0, progress: progress) + } + ) return try self.git.run( ["-C", self.path.pathString] + args, environment: environment, @@ -462,7 +470,8 @@ public final class GitRepository: Repository, WorkingCheckout { environment: error.result.environment, exitStatus: error.result.exitStatus, output: .success(stdoutBytes), - stderrOutput: .success(stderrBytes)) + stderrOutput: .success(stderrBytes) + ) throw GitRepositoryError(path: self.path, message: failureMessage, result: result) } } else { @@ -611,12 +620,14 @@ public final class GitRepository: Repository, WorkingCheckout { public func getCurrentRevision() throws -> Revision { try self.lock.withLock { - try Revision(identifier: callGit( - "rev-parse", - "--verify", - "HEAD", - failureMessage: "Couldn’t get current revision" - )) + try Revision( + identifier: callGit( + "rev-parse", + "--verify", + "HEAD", + failureMessage: "Couldn’t get current revision" + ) + ) } } @@ -777,13 +788,15 @@ public final class GitRepository: Repository, WorkingCheckout { output = try error.result.utf8Output().spm_chomp() } - return stringPaths.map(output.split(whereSeparator: { $0.isNewline }).map { - let string = String($0).replacing("\\\\", with: "\\") - if string.utf8.first == UInt8(ascii: "\"") { - return String(string.dropFirst(1).dropLast(1)) - } - return string - }.contains) + return stringPaths.map( + output.split(whereSeparator: { $0.isNewline }).map { + let string = String($0).replacing("\\\\", with: "\\") + if string.utf8.first == UInt8(ascii: "\"") { + return String(string.dropFirst(1).dropLast(1)) + } + return string + }.contains + ) } } @@ -880,22 +893,22 @@ public final class GitRepository: Repository, WorkingCheckout { let bytes = ByteString(encodingAsUTF8: line) let expectedBytesCount = 6 + 1 + 4 + 1 + 40 + 1 guard bytes.count > expectedBytesCount, - bytes.contents[6] == UInt8(ascii: " "), - // Search for the second space since `type` is of variable length. - let secondSpace = bytes.contents[6 + 1 ..< bytes.contents.endIndex].firstIndex(of: UInt8(ascii: " ")), - bytes.contents[secondSpace] == UInt8(ascii: " "), - bytes.contents[secondSpace + 1 + 40] == UInt8(ascii: "\t") + bytes.contents[6] == UInt8(ascii: " "), + // Search for the second space since `type` is of variable length. + let secondSpace = bytes.contents[6 + 1.. String { return try callGit( - "cat-file", "-p", String(describing: hash.bytes), + "cat-file", + "-p", + String(describing: hash.bytes), failureMessage: "Couldn't read '\(String(describing: hash.bytes))'" ) } @@ -1244,29 +1259,30 @@ public enum GitProgressParser: FetchProgress { /// The pattern used to match git output. Capture groups are labeled from ? to ?. static let pattern = #""" - (?xi) - (?: - remote: \h+ (?Enumerating \h objects): \h+ (?[0-9]+) - )| - (?: - remote: \h+ (?Counting \h objects): \h+ (?[0-9]+)% \h+ \((?[0-9]+)\/(?[0-9]+)\) - )| - (?: - remote: \h+ (?Compressing \h objects): \h+ (?[0-9]+)% \h+ \((?[0-9]+)\/(?[0-9]+)\) - )| - (?: - (?Resolving \h deltas): \h+ (?[0-9]+)% \h+ \((?[0-9]+)\/(?[0-9]+)\) - )| - (?: - (?Receiving \h objects): \h+ (?[0-9]+)% \h+ \((?[0-9]+)\/(?[0-9]+)\) - (?:, \h+ (?[0-9]+.?[0-9]+ \h [A-Z]iB) \h+ \| \h+ (?[0-9]+.?[0-9]+ \h [A-Z]iB\/s))? - ) - """# + (?xi) + (?: + remote: \h+ (?Enumerating \h objects): \h+ (?[0-9]+) + )| + (?: + remote: \h+ (?Counting \h objects): \h+ (?[0-9]+)% \h+ \((?[0-9]+)\/(?[0-9]+)\) + )| + (?: + remote: \h+ (?Compressing \h objects): \h+ (?[0-9]+)% \h+ \((?[0-9]+)\/(?[0-9]+)\) + )| + (?: + (?Resolving \h deltas): \h+ (?[0-9]+)% \h+ \((?[0-9]+)\/(?[0-9]+)\) + )| + (?: + (?Receiving \h objects): \h+ (?[0-9]+)% \h+ \((?[0-9]+)\/(?[0-9]+)\) + (?:, \h+ (?[0-9]+.?[0-9]+ \h [A-Z]iB) \h+ \| \h+ (?[0-9]+.?[0-9]+ \h [A-Z]iB\/s))? + ) + """# static let regex = try? RegEx(pattern: pattern) init?(from string: String) { guard let matches = GitProgressParser.regex?.matchGroups(in: string).first, - matches.count == 20 else { return nil } + matches.count == 20 + else { return nil } if matches[0] == "Enumerating objects" { guard let currentObjects = Int(matches[1]) else { return nil } @@ -1274,8 +1290,9 @@ public enum GitProgressParser: FetchProgress { self = .enumeratingObjects(currentObjects: currentObjects) } else if matches[2] == "Counting objects" { guard let progress = Double(matches[3]), - let currentObjects = Int(matches[4]), - let totalObjects = Int(matches[5]) else { return nil } + let currentObjects = Int(matches[4]), + let totalObjects = Int(matches[5]) + else { return nil } self = .countingObjects( progress: progress / 100, @@ -1285,8 +1302,9 @@ public enum GitProgressParser: FetchProgress { } else if matches[6] == "Compressing objects" { guard let progress = Double(matches[7]), - let currentObjects = Int(matches[8]), - let totalObjects = Int(matches[9]) else { return nil } + let currentObjects = Int(matches[8]), + let totalObjects = Int(matches[9]) + else { return nil } self = .compressingObjects( progress: progress / 100, @@ -1296,8 +1314,9 @@ public enum GitProgressParser: FetchProgress { } else if matches[10] == "Resolving deltas" { guard let progress = Double(matches[11]), - let currentObjects = Int(matches[12]), - let totalObjects = Int(matches[13]) else { return nil } + let currentObjects = Int(matches[12]), + let totalObjects = Int(matches[13]) + else { return nil } self = .resolvingDeltas( progress: progress / 100, @@ -1307,8 +1326,9 @@ public enum GitProgressParser: FetchProgress { } else if matches[14] == "Receiving objects" { guard let progress = Double(matches[15]), - let currentObjects = Int(matches[16]), - let totalObjects = Int(matches[17]) else { return nil } + let currentObjects = Int(matches[16]), + let totalObjects = Int(matches[17]) + else { return nil } let downloadProgress = matches[18] let downloadSpeed = matches[19] @@ -1388,7 +1408,8 @@ public enum GitProgressParser: FetchProgress { /// Processes stdout output and calls the progress callback with `GitStatus` objects. private func gitFetchStatusFilter(_ bytes: [UInt8], progress: FetchProgress.Handler) { guard let string = String(bytes: bytes, encoding: .utf8) else { return } - let lines = string + let lines = + string .split { $0.isNewline } .map { String($0) } diff --git a/Sources/SourceControl/Repository.swift b/Sources/SourceControl/Repository.swift index 71a438681c1..126b13b1359 100644 --- a/Sources/SourceControl/Repository.swift +++ b/Sources/SourceControl/Repository.swift @@ -121,7 +121,8 @@ public protocol RepositoryProvider: Cancellable, Sendable { repository: RepositorySpecifier, sourcePath: AbsolutePath, at destinationPath: AbsolutePath, - editable: Bool) async throws -> WorkingCheckout + editable: Bool + ) async throws -> WorkingCheckout /// Returns true if a working repository exists at `path` func workingCopyExists(at path: AbsolutePath) throws -> Bool diff --git a/Sources/SourceControl/RepositoryManager.swift b/Sources/SourceControl/RepositoryManager.swift index 6cbf8bde3ac..7a7bf3a267e 100644 --- a/Sources/SourceControl/RepositoryManager.swift +++ b/Sources/SourceControl/RepositoryManager.swift @@ -65,7 +65,7 @@ public class RepositoryManager: Cancellable { fileSystem: FileSystem, path: Basics.AbsolutePath, provider: RepositoryProvider, - cachePath: Basics.AbsolutePath? = .none, + cachePath: Basics.AbsolutePath? = .none, cacheLocalPackages: Bool = false, maxConcurrentOperations: Int? = .none, initializationWarningHandler: (String) -> Void, @@ -418,7 +418,8 @@ public class RepositoryManager: Cancellable { repository: handle.repository, sourcePath: self.path.appending(handle.subpath), at: destinationPath, - editable: editable) + editable: editable + ) } /// Removes the repository. @@ -602,7 +603,6 @@ fileprivate actor RepositoryManagerDelegateProxy { } } - extension RepositoryManager.RepositoryHandle: CustomStringConvertible { public var description: String { return "<\(type(of: self)) subpath:\(subpath)>" @@ -646,44 +646,48 @@ extension RepositorySpecifier { } #if canImport(SystemConfiguration) -import SystemConfiguration + import SystemConfiguration -private struct Reachability { - let reachability: SCNetworkReachability + private struct Reachability { + let reachability: SCNetworkReachability - init?() { - var emptyAddress = sockaddr() - emptyAddress.sa_len = UInt8(MemoryLayout.size) - emptyAddress.sa_family = sa_family_t(AF_INET) + init?() { + var emptyAddress = sockaddr() + emptyAddress.sa_len = UInt8(MemoryLayout.size) + emptyAddress.sa_family = sa_family_t(AF_INET) - guard let reachability = withUnsafePointer(to: &emptyAddress, { - SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) - }) else { - return nil + guard + let reachability = withUnsafePointer( + to: &emptyAddress, + { + SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) + } + ) + else { + return nil + } + self.reachability = reachability } - self.reachability = reachability - } - var connectionRequired: Bool { - var flags = SCNetworkReachabilityFlags() - let hasFlags = withUnsafeMutablePointer(to: &flags) { - SCNetworkReachabilityGetFlags(reachability, UnsafeMutablePointer($0)) - } - guard hasFlags else { return false } - guard flags.contains(.reachable) else { - return true + var connectionRequired: Bool { + var flags = SCNetworkReachabilityFlags() + let hasFlags = withUnsafeMutablePointer(to: &flags) { + SCNetworkReachabilityGetFlags(reachability, UnsafeMutablePointer($0)) + } + guard hasFlags else { return false } + guard flags.contains(.reachable) else { + return true + } + return flags.contains(.connectionRequired) || flags.contains(.transientConnection) } - return flags.contains(.connectionRequired) || flags.contains(.transientConnection) } -} -fileprivate func isOffline(_ error: Swift.Error) -> Bool { - return Reachability()?.connectionRequired == true -} + fileprivate func isOffline(_ error: Swift.Error) -> Bool { + return Reachability()?.connectionRequired == true + } #else -fileprivate func isOffline(_ error: Swift.Error) -> Bool { - // TODO: Find a better way to determine reachability on non-Darwin platforms. - return "\(error)".contains("Could not resolve host") -} + fileprivate func isOffline(_ error: Swift.Error) -> Bool { + // TODO: Find a better way to determine reachability on non-Darwin platforms. + return "\(error)".contains("Could not resolve host") + } #endif - diff --git a/Sources/SourceKitLSPAPI/BuildDescription.swift b/Sources/SourceKitLSPAPI/BuildDescription.swift index aa7dd5f6ca5..6e44b5c6f96 100644 --- a/Sources/SourceKitLSPAPI/BuildDescription.swift +++ b/Sources/SourceKitLSPAPI/BuildDescription.swift @@ -122,7 +122,6 @@ private struct WrappedClangTargetBuildDescription: BuildTarget { var compiler: BuildTargetCompiler { .clang } - public var destination: BuildDestination { return description.destination == .host ? .host : .target } @@ -288,11 +287,12 @@ public struct BuildDescription { callback: (any BuildTarget, _ parent: (any BuildTarget)?) -> Void ) { self.buildPlan.traverseModules { module, parent in - let parentDescription: (any BuildTarget)? = if let parent { - getBuildTarget(for: parent.0, destination: parent.1) - } else { - nil - } + let parentDescription: (any BuildTarget)? = + if let parent { + getBuildTarget(for: parent.0, destination: parent.1) + } else { + nil + } if let description = getBuildTarget(for: module.0, destination: module.1) { callback(description, parentDescription) diff --git a/Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift b/Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift index b55aeb86067..ebe54b11a45 100644 --- a/Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift +++ b/Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift @@ -34,7 +34,7 @@ struct PluginTargetBuildDescription: BuildTarget { var sources: [SourceItem] { return target.sources.paths.map { - SourceItem(sourceFile: $0.asURL, outputFile: nil) + SourceItem(sourceFile: $0.asURL, outputFile: nil) } } @@ -82,37 +82,37 @@ struct PluginTargetBuildDescription: BuildTarget { } fileprivate enum FilePathError: Error, CustomStringConvertible { - case noFileSystemRepresentation(URL) - case noFileURL(URL) - - var description: String { - switch self { - case .noFileSystemRepresentation(let url): - return "\(url.description) cannot be represented as a file system path" - case .noFileURL(let url): - return "\(url.description) is not a file URL" + case noFileSystemRepresentation(URL) + case noFileURL(URL) + + var description: String { + switch self { + case .noFileSystemRepresentation(let url): + return "\(url.description) cannot be represented as a file system path" + case .noFileURL(let url): + return "\(url.description) is not a file URL" + } } - } } fileprivate extension URL { - /// Assuming that this is a file URL, the path with which the file system refers to the file. This is similar to - /// `path` but has two differences: - /// - It uses backslashes as the path separator on Windows instead of forward slashes - /// - It throws an error when called on a non-file URL. - /// - /// `filePath` should generally be preferred over `path` when dealing with file URLs. - var filePath: String { - get throws { - guard self.isFileURL else { - throw FilePathError.noFileURL(self) - } - return try self.withUnsafeFileSystemRepresentation { buffer in - guard let buffer else { - throw FilePathError.noFileSystemRepresentation(self) + /// Assuming that this is a file URL, the path with which the file system refers to the file. This is similar to + /// `path` but has two differences: + /// - It uses backslashes as the path separator on Windows instead of forward slashes + /// - It throws an error when called on a non-file URL. + /// + /// `filePath` should generally be preferred over `path` when dealing with file URLs. + var filePath: String { + get throws { + guard self.isFileURL else { + throw FilePathError.noFileURL(self) + } + return try self.withUnsafeFileSystemRepresentation { buffer in + guard let buffer else { + throw FilePathError.noFileSystemRepresentation(self) + } + return String(cString: buffer) + } } - return String(cString: buffer) - } } - } } diff --git a/Sources/SwiftBuildSupport/DotPIFSerializer.swift b/Sources/SwiftBuildSupport/DotPIFSerializer.swift index 5cf883ee15c..dc1bf11bc21 100644 --- a/Sources/SwiftBuildSupport/DotPIFSerializer.swift +++ b/Sources/SwiftBuildSupport/DotPIFSerializer.swift @@ -92,7 +92,7 @@ fileprivate struct DotPIFSerializer { func write(_ object: String) { outputStream.write("\(object)\n") } write("digraph PIF {") - write(" dpi=400;") // i.e., MacBook Pro 16" is 226 pixels per inch (3072 x 1920). + write(" dpi=400;") // i.e., MacBook Pro 16" is 226 pixels per inch (3072 x 1920). for object in objects { write(" \(object);") } @@ -230,10 +230,10 @@ fileprivate extension PIF.GUID { fileprivate extension String { /// Quote the name and escape the quotes and backslashes. var quote: String { - "\"" + self + "\"" + + self .replacing("\"", with: "\\\"") .replacing("\\", with: "\\\\") - .replacing("\n", with: "\\n") + - "\"" + .replacing("\n", with: "\\n") + "\"" } } diff --git a/Sources/SwiftBuildSupport/PIF.swift b/Sources/SwiftBuildSupport/PIF.swift index ff2fde612a1..32d2daecf02 100644 --- a/Sources/SwiftBuildSupport/PIF.swift +++ b/Sources/SwiftBuildSupport/PIF.swift @@ -31,30 +31,30 @@ import enum SwiftBuild.ProjectModel public enum PIF { /// The type used for identifying PIF objects. public typealias GUID = ProjectModel.GUID - + /// The top-level PIF object. public struct TopLevelObject: Encodable { public let workspace: PIF.Workspace - + public init(workspace: PIF.Workspace) { self.workspace = workspace } - + public func encode(to encoder: Encoder) throws { var container = encoder.unkeyedContainer() - + // Encode the workspace. try container.encode(workspace) - + // Encode the projects and their targets. for project in workspace.projects { try container.encode(project) let targets = project.underlying.targets - + for target in targets where !target.id.hasSuffix(.dynamic) { try container.encode(Target(wrapping: target)) } - + // Add *dynamic variants* at the end just to have a clear split from other targets. for target in targets where target.id.hasSuffix(.dynamic) { try container.encode(Target(wrapping: target)) @@ -62,7 +62,7 @@ public enum PIF { } } } - + /// Represents a high-level PIF object. /// /// For instance, a JSON serialized *workspace* might look like this: @@ -85,37 +85,37 @@ public enum PIF { class var type: String { fatalError("\(self) missing implementation") } - + let type: String - + fileprivate init() { type = Self.type } - + fileprivate enum CodingKeys: CodingKey { case type - case signature, contents // Used by subclasses. + case signature, contents // Used by subclasses. } - + public func encode(to encoder: Encoder) throws { var superContainer = encoder.container(keyedBy: CodingKeys.self) try superContainer.encode(type, forKey: .type) } - + required public init(from decoder: Decoder) throws { let superContainer = try decoder.container(keyedBy: CodingKeys.self) self.type = try superContainer.decode(String.self, forKey: .type) - + guard self.type == Self.type else { throw InternalError("Expected same type for high-level object: \(self.type)") } } } - + /// The high-level PIF *workspace* object. public final class Workspace: HighLevelObject { override class var type: String { "workspace" } - + public let id: GUID public var name: String public var path: AbsolutePath @@ -126,29 +126,29 @@ public enum PIF { precondition(!id.value.isEmpty) precondition(!name.isEmpty) precondition(Set(projects.map(\.id)).count == projects.count) - + self.id = id self.name = name self.path = path self.projects = projects.map { Project(wrapping: $0) } super.init() } - + private enum CodingKeys: CodingKey { case guid, name, path, projects } - + public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) - + var superContainer = encoder.container(keyedBy: HighLevelObject.CodingKeys.self) var contents = superContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .contents) - + try contents.encode("\(id)", forKey: .guid) try contents.encode(name, forKey: .name) try contents.encode(path, forKey: .path) try contents.encode(projects.map(\.signature), forKey: .projects) - + if encoder.userInfo.keys.contains(.encodeForSwiftBuild) { guard let signature else { throw InternalError("Expected to have workspace *signature* when encoding for SwiftBuild") @@ -156,42 +156,42 @@ public enum PIF { try superContainer.encode(signature, forKey: .signature) } } - + // FIXME: Delete this (https://github.com/swiftlang/swift-package-manager/issues/8552). public required init(from decoder: Decoder) throws { let superContainer = try decoder.container(keyedBy: HighLevelObject.CodingKeys.self) let contents = try superContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .contents) - + self.id = try contents.decode(GUID.self, forKey: .guid) self.name = try contents.decode(String.self, forKey: .name) self.path = try contents.decode(AbsolutePath.self, forKey: .path) self.projects = try contents.decode([Project].self, forKey: .projects) - + try super.init(from: decoder) } } - + /// A high-level PIF *project* object. public final class Project: HighLevelObject { override class var type: String { "project" } - + public var underlying: ProjectModel.Project var signature: String? var id: ProjectModel.GUID { underlying.id } - + public init(wrapping underlying: ProjectModel.Project) { precondition(!underlying.name.isEmpty) precondition(!underlying.id.value.isEmpty) precondition(!underlying.path.isEmpty) precondition(!underlying.projectDir.isEmpty) - + precondition(Set(underlying.targets.map(\.id)).count == underlying.targets.count) precondition(Set(underlying.buildConfigs.map(\.id)).count == underlying.buildConfigs.count) - + self.underlying = underlying super.init() } - + public override func encode(to encoder: any Encoder) throws { try super.encode(to: encoder) var superContainer = encoder.container(keyedBy: HighLevelObject.CodingKeys.self) @@ -204,31 +204,31 @@ public enum PIF { try superContainer.encode(signature, forKey: .signature) } } - + // FIXME: Delete this (https://github.com/swiftlang/swift-package-manager/issues/8552). public required init(from decoder: Decoder) throws { let superContainer = try decoder.container(keyedBy: HighLevelObject.CodingKeys.self) self.underlying = try superContainer.decode(ProjectModel.Project.self, forKey: .contents) - + try super.init(from: decoder) } } - + /// A high-level PIF *target* object. private final class Target: HighLevelObject { override class var type: String { "target" } - + public var underlying: ProjectModel.BaseTarget var id: ProjectModel.GUID { underlying.id } - + public init(wrapping underlying: ProjectModel.BaseTarget) { precondition(!underlying.id.value.isEmpty) precondition(!underlying.common.name.isEmpty) - + self.underlying = underlying super.init() } - + public override func encode(to encoder: any Encoder) throws { try super.encode(to: encoder) var superContainer = encoder.container(keyedBy: HighLevelObject.CodingKeys.self) @@ -241,7 +241,7 @@ public enum PIF { try superContainer.encode(signature, forKey: .signature) } } - + public required init(from decoder: Decoder) throws { // FIXME: Remove all support for decoding PIF objects in SwiftBuildSupport? // (https://github.com/swiftlang/swift-package-manager/issues/8552) diff --git a/Sources/SwiftBuildSupport/PIFBuilder.swift b/Sources/SwiftBuildSupport/PIFBuilder.swift index 6e304910499..faa7b79e38c 100644 --- a/Sources/SwiftBuildSupport/PIFBuilder.swift +++ b/Sources/SwiftBuildSupport/PIFBuilder.swift @@ -17,8 +17,7 @@ import PackageLoading import PackageModel import TSCUtility -@_spi(SwiftPMInternal) -import SPMBuildCore +@_spi(SwiftPMInternal) import SPMBuildCore import func TSCBasic.topologicalSort import var TSCBasic.stdoutStream @@ -208,7 +207,7 @@ public final class PIFBuilder { let outputDir = self.parameters.pluginWorkingDirectory.appending("outputs") let pluginsPerModule = graph.pluginsPerModule( - satisfying: buildParameters.buildEnvironment // .buildEnvironment(for: .host) + satisfying: buildParameters.buildEnvironment // .buildEnvironment(for: .host) ) let availablePluginTools = try await availableBuildPluginTools( @@ -228,10 +227,10 @@ public final class PIFBuilder { } let sortedPackages = self.graph.packages - .sorted { $0.manifest.displayName < $1.manifest.displayName } // TODO: use identity instead? - + .sorted { $0.manifest.displayName < $1.manifest.displayName } // TODO: use identity instead? + var packagesAndProjects: [(ResolvedPackage, ProjectModel.Project)] = [] - + for package in sortedPackages { var buildToolPluginResultsByTargetName: [String: [PackagePIFBuilder.BuildToolPluginInvocationResult]] = [:] @@ -336,48 +335,50 @@ public final class PIFBuilder { prebuildCommands.append(contentsOf: result.prebuildCommands) - buildCommands.append(contentsOf: result.buildCommands.map( { buildCommand in - var newEnv: Environment = buildCommand.configuration.environment - - // FIXME: This is largely a workaround for improper rpath setup on Linux. It should be - // removed once the Swift Build backend switches to use swiftc as the linker driver - // for targets with Swift sources. For now, limit the scope to non-macOS, so that - // plugins do not inadvertently use the toolchain stdlib instead of the OS stdlib - // when built with a Swift.org toolchain. - #if !os(macOS) - let runtimeLibPaths = buildParameters.toolchain.runtimeLibraryPaths - - // Add paths to swift standard runtime libraries to the library path so that they can be found at runtime - for libPath in runtimeLibPaths { - newEnv.appendPath(key: .libraryPath, value: libPath.pathString) - } - #endif - - // Append the system path at the end so that necessary system tool paths can be found - if let pathValue = Environment.current[EnvironmentKey.path] { - newEnv.appendPath(key: .path, value: pathValue) - } - - let writableDirectories: [AbsolutePath] = [pluginOutputDir] - - return PackagePIFBuilder.CustomBuildCommand( - displayName: buildCommand.configuration.displayName, - executable: buildCommand.configuration.executable.pathString, - arguments: buildCommand.configuration.arguments, - environment: .init(newEnv), - workingDir: package.path, - inputPaths: buildCommand.inputFiles, - outputPaths: buildCommand.outputFiles.map(\.pathString), - sandboxProfile: - self.parameters.disableSandbox ? - nil : - .init( + buildCommands.append( + contentsOf: result.buildCommands.map({ buildCommand in + var newEnv: Environment = buildCommand.configuration.environment + + // FIXME: This is largely a workaround for improper rpath setup on Linux. It should be + // removed once the Swift Build backend switches to use swiftc as the linker driver + // for targets with Swift sources. For now, limit the scope to non-macOS, so that + // plugins do not inadvertently use the toolchain stdlib instead of the OS stdlib + // when built with a Swift.org toolchain. + #if !os(macOS) + let runtimeLibPaths = buildParameters.toolchain.runtimeLibraryPaths + + // Add paths to swift standard runtime libraries to the library path so that they can be found at runtime + for libPath in runtimeLibPaths { + newEnv.appendPath(key: .libraryPath, value: libPath.pathString) + } + #endif + + // Append the system path at the end so that necessary system tool paths can be found + if let pathValue = Environment.current[EnvironmentKey.path] { + newEnv.appendPath(key: .path, value: pathValue) + } + + let writableDirectories: [AbsolutePath] = [pluginOutputDir] + + return PackagePIFBuilder.CustomBuildCommand( + displayName: buildCommand.configuration.displayName, + executable: buildCommand.configuration.executable.pathString, + arguments: buildCommand.configuration.arguments, + environment: .init(newEnv), + workingDir: package.path, + inputPaths: buildCommand.inputFiles, + outputPaths: buildCommand.outputFiles.map(\.pathString), + sandboxProfile: + self.parameters.disableSandbox + ? nil + : .init( strictness: .writableTemporaryDirectory, writableDirectories: writableDirectories, readOnlyDirectories: buildCommand.inputFiles ) - ) - })) + ) + }) + ) } // Run the prebuild commands generated from the plugin invocation now for this module. This will @@ -390,7 +391,7 @@ public final class PIFBuilder { ) let result = PackagePIFBuilder.BuildToolPluginInvocationResult( - prebuildCommandOutputPaths: runResults.flatMap( { $0.derivedFiles }), + prebuildCommandOutputPaths: runResults.flatMap({ $0.derivedFiles }), buildCommands: buildCommands ) @@ -417,11 +418,11 @@ public final class PIFBuilder { fileSystem: self.fileSystem, observabilityScope: self.observabilityScope ) - + try packagePIFBuilder.build() packagesAndProjects.append((package, packagePIFBuilder.pifProject)) } - + var projects = packagesAndProjects.map(\.1) projects.append( try buildAggregateProject( @@ -434,7 +435,7 @@ public final class PIFBuilder { let workspace = PIF.Workspace( id: "Workspace:\(rootPackage.path.pathString)", - name: rootPackage.manifest.displayName, // TODO: use identity instead? + name: rootPackage.manifest.displayName, // TODO: use identity instead? path: rootPackage.path, projects: projects ) @@ -460,8 +461,7 @@ public final class PIFBuilder { for command in pluginResult.prebuildCommands { observabilityScope .emit( - info: "Running " + - (command.configuration.displayName ?? command.configuration.executable.basename) + info: "Running " + (command.configuration.displayName ?? command.configuration.executable.basename) ) // Run the command configuration as a subshell. This doesn't return until it is done. @@ -534,35 +534,35 @@ public final class PIFBuilder { fileprivate final class PackagePIFBuilderDelegate: PackagePIFBuilder.BuildDelegate { let package: ResolvedPackage - + init(package: ResolvedPackage) { self.package = package } - + var isRootPackage: Bool { self.package.manifest.packageKind.isRoot } - + var hostsOnlyPackages: Bool { false } - + var isUserManaged: Bool { true } - + var isBranchOrRevisionBased: Bool { false } - + func customProductType(forExecutable product: PackageModel.Product) -> ProjectModel.Target.ProductType? { nil } - + func deviceFamilyIDs() -> Set { [] } - + func shouldPackagesBuildForARM64e(platform: PackageModel.Platform) -> Bool { false } @@ -570,43 +570,43 @@ fileprivate final class PackagePIFBuilderDelegate: PackagePIFBuilder.BuildDelega var isPluginExecutionSandboxingDisabled: Bool { false } - + func configureProjectBuildSettings(_ buildSettings: inout ProjectModel.BuildSettings) { /* empty */ } - + func configureSourceModuleBuildSettings(sourceModule: ResolvedModule, settings: inout ProjectModel.BuildSettings) { /* empty */ } - + func customInstallPath(product: PackageModel.Product) -> String? { nil } - + func customExecutableName(product: PackageModel.Product) -> String? { nil } - + func customLibraryType(product: PackageModel.Product) -> PackageModel.ProductType.LibraryType? { nil } - + func customSDKOptions(forPlatform: PackageModel.Platform) -> [String] { [] } - + func addCustomTargets(pifProject: inout SwiftBuild.ProjectModel.Project) throws -> [PackagePIFBuilder.ModuleOrProduct] { return [] } - + func shouldSuppressProductDependency(product: PackageModel.Product, buildSettings: inout SwiftBuild.ProjectModel.BuildSettings) -> Bool { false } - + func shouldSetInstallPathForDynamicLib(productName: String) -> Bool { false } - + func configureLibraryProduct( product: PackageModel.Product, project: inout ProjectModel.Project, @@ -615,11 +615,11 @@ fileprivate final class PackagePIFBuilderDelegate: PackagePIFBuilder.BuildDelega ) { /* empty */ } - + func suggestAlignedPlatformVersionGiveniOSVersion(platform: PackageModel.Platform, iOSVersion: PackageModel.PlatformVersion) -> String? { nil } - + func validateMacroFingerprint(for macroModule: ResolvedModule) -> Bool { true } @@ -632,7 +632,7 @@ fileprivate func buildAggregateProject( buildParameters: BuildParameters ) throws -> ProjectModel.Project { precondition(!packagesAndProjects.isEmpty) - + var aggregateProject = ProjectModel.Project( id: "AGGREGATE", path: packagesAndProjects[0].project.path, @@ -641,17 +641,17 @@ fileprivate func buildAggregateProject( developmentRegion: "en" ) observabilityScope.logPIF(.debug, "Created project '\(aggregateProject.id)' with name '\(aggregateProject.name)'") - + var settings = ProjectModel.BuildSettings() settings[.PRODUCT_NAME] = "$(TARGET_NAME)" settings[.SUPPORTED_PLATFORMS] = ["$(AVAILABLE_PLATFORMS)"] settings[.SDKROOT] = "auto" settings[.SDK_VARIANT] = "auto" settings[.SKIP_INSTALL] = "YES" - + aggregateProject.addBuildConfig { id in BuildConfig(id: id, name: "Debug", settings: settings) } aggregateProject.addBuildConfig { id in BuildConfig(id: id, name: "Release", settings: settings) } - + func addEmptyBuildConfig( to targetKeyPath: WritableKeyPath, name: String @@ -661,7 +661,7 @@ fileprivate func buildAggregateProject( BuildConfig(id: id, name: name, settings: emptySettings) } } - + let allIncludingTestsTargetKeyPath = try aggregateProject.addAggregateTarget { _ in ProjectModel.AggregateTarget( id: "ALL-INCLUDING-TESTS", @@ -670,7 +670,7 @@ fileprivate func buildAggregateProject( } addEmptyBuildConfig(to: allIncludingTestsTargetKeyPath, name: "Debug") addEmptyBuildConfig(to: allIncludingTestsTargetKeyPath, name: "Release") - + let allExcludingTestsTargetKeyPath = try aggregateProject.addAggregateTarget { _ in ProjectModel.AggregateTarget( id: "ALL-EXCLUDING-TESTS", @@ -679,7 +679,7 @@ fileprivate func buildAggregateProject( } addEmptyBuildConfig(to: allExcludingTestsTargetKeyPath, name: "Debug") addEmptyBuildConfig(to: allExcludingTestsTargetKeyPath, name: "Release") - + for (package, packageProject) in packagesAndProjects where package.manifest.packageKind.isRoot { for target in packageProject.targets { switch target { @@ -715,31 +715,29 @@ fileprivate func buildAggregateProject( } } } - + do { let allIncludingTests = aggregateProject[keyPath: allIncludingTestsTargetKeyPath] let allExcludingTests = aggregateProject[keyPath: allExcludingTestsTargetKeyPath] - + observabilityScope.logPIF( .debug, indent: 1, - "Created target '\(allIncludingTests.id)' with name '\(allIncludingTests.name)' " + - "and \(allIncludingTests.common.dependencies.count) (unlinked) dependencies" + "Created target '\(allIncludingTests.id)' with name '\(allIncludingTests.name)' " + "and \(allIncludingTests.common.dependencies.count) (unlinked) dependencies" ) observabilityScope.logPIF( .debug, indent: 1, - "Created target '\(allExcludingTests.id)' with name '\(allExcludingTests.name)' " + - "and \(allExcludingTests.common.dependencies.count) (unlinked) dependencies" + "Created target '\(allExcludingTests.id)' with name '\(allExcludingTests.name)' " + "and \(allExcludingTests.common.dependencies.count) (unlinked) dependencies" ) } - + return aggregateProject } public enum PIFGenerationError: Error { case rootPackageNotFound, multipleRootPackagesFound - + case unsupportedSwiftLanguageVersions( targetName: String, versions: [SwiftLanguageVersion], @@ -764,8 +762,7 @@ extension PIFGenerationError: CustomStringConvertible { versions: let given, supportedVersions: let supported ): - "None of the Swift language versions used in target '\(target)' settings are supported." + - " (given: \(given), supported: \(supported))" + "None of the Swift language versions used in target '\(target)' settings are supported." + " (given: \(given), supported: \(supported))" case .printedPIFManifestGraphviz: "Printed PIF manifest as graphviz" diff --git a/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift b/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift index 60a2a177f73..625f3c4a19b 100644 --- a/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift +++ b/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift @@ -63,7 +63,7 @@ import enum SwiftBuild.ProjectModel enum TargetSuffix: String { case testable, dynamic - + func hasSuffix(id: GUID) -> Bool { id.value.hasSuffix("-\(self.rawValue)") } @@ -106,7 +106,7 @@ extension PackageModel.Product { var pifTargetGUID: GUID { pifTargetGUID(suffix: nil) } func pifTargetGUID(suffix: TargetSuffix?) -> GUID { - PackagePIFBuilder.targetGUID(forProductName: self.name, withId:self.identity, suffix: suffix) + PackagePIFBuilder.targetGUID(forProductName: self.name, withId: self.identity, suffix: suffix) } } @@ -235,7 +235,8 @@ extension Sequence { return [] } - var pifPlatformsForCondition: [ProjectModel.BuildSettings.Platform] = platforms + var pifPlatformsForCondition: [ProjectModel.BuildSettings.Platform] = + platforms .compactMap { try? ProjectModel.BuildSettings.Platform(from: $0) } // Treat catalyst like macOS for backwards compatibility with older tools versions. @@ -247,11 +248,13 @@ extension Sequence { return Set(pifPlatforms.flatMap { $0.toPlatformFilter() }) } - var splitIntoConcreteConditions: ( - [PackageModel.Platform?], - [PackageModel.BuildConfiguration], - [PackageModel.TraitCondition] - ) { + var splitIntoConcreteConditions: + ( + [PackageModel.Platform?], + [PackageModel.BuildConfiguration], + [PackageModel.TraitCondition] + ) + { var platformConditions: [PackageModel.PlatformsCondition] = [] var configurationConditions: [PackageModel.ConfigurationCondition] = [] var traitConditions: [PackageModel.TraitCondition] = [] @@ -266,19 +269,21 @@ extension Sequence { // Determine the *platform* conditions, if any. // An empty set means that there are no platform restrictions. - let platforms: [PackageModel.Platform?] = if platformConditions.isEmpty { - [nil] - } else { - platformConditions.flatMap(\.platforms) - } + let platforms: [PackageModel.Platform?] = + if platformConditions.isEmpty { + [nil] + } else { + platformConditions.flatMap(\.platforms) + } // Determine the *configuration* conditions, if any. // If there are none, we apply the setting to both debug and release builds (ie, `allCases`). - let configurations: [BuildConfiguration] = if configurationConditions.isEmpty { - BuildConfiguration.allCases - } else { - configurationConditions.map(\.configuration) - } + let configurations: [BuildConfiguration] = + if configurationConditions.isEmpty { + BuildConfiguration.allCases + } else { + configurationConditions.map(\.configuration) + } return (platforms, configurations, traitConditions) } @@ -502,16 +507,13 @@ extension PackageGraph.ResolvedModule { mainModuleProducts.only { (mainModuleProduct: ResolvedProduct) -> Bool in // Handle binary-only executable products that don't have a main module, i.e. binaryTarget guard let mainModule = mainModuleProduct.mainModule else { - return mainModuleProduct.type == .executable && - mainModuleProduct.modules.only?.type == .binary && - mainModuleProduct.modules.only?.name == self.name + return mainModuleProduct.type == .executable && mainModuleProduct.modules.only?.type == .binary && mainModuleProduct.modules.only?.name == self.name } // NOTE: We can't use the 'id' here as we need to explicitly ignore the build triple because our build // triple will be '.tools' while the target we want to depend on will have a build triple of '.destination'. // See for more details: // https://github.com/swiftlang/swift-package-manager/commit/b22168ec41061ddfa3438f314a08ac7a776bef7a. - return mainModule.packageIdentity == self.packageIdentity && - mainModule.name == self.name + return mainModule.packageIdentity == self.packageIdentity && mainModule.name == self.name // Intentionally ignore the build triple! } } @@ -524,18 +526,18 @@ extension PackageGraph.ResolvedModule { /// Target-specific single-value build settings declared in the manifest and that apply to the target itself. var targetSingleValueSettings: [BuildConfiguration: SingleValueSettingsByPlatform] = [:] - + /// Target-specific multiple-value build settings declared in the manifest and that apply to the target itself. var targetMultipleValueSettings: [BuildConfiguration: MultipleValueSettingsByPlatform] = [:] /// Target-specific single-value build settings that should be imparted to client targets (packages and projects). var impartedSingleValueSettings: SingleValueSettingsByPlatform = [:] - + /// Target-specific multiple-value build settings that should be imparted to client targets (packages and projects). var impartedMultipleValueSettings: MultipleValueSettingsByPlatform = [:] - + // MARK: - Convenience Methods - + /// Apply all settings to a ProjectModel.BuildSettings instance func apply(to buildSettings: inout ProjectModel.BuildSettings, for configuration: BuildConfiguration) { // Apply single value settings for all platforms @@ -550,7 +552,7 @@ extension PackageGraph.ResolvedModule { } } } - + // Apply multiple value settings for all platforms if let multipleValuesByPlatform = targetMultipleValueSettings[configuration] { // First, collect all multiple-value settings that are being used @@ -560,7 +562,7 @@ extension PackageGraph.ResolvedModule { usedMultipleValueSettings.insert(setting) } } - + // Now apply the platform-specific values for (platform, multipleValues) in multipleValuesByPlatform { for (setting, values) in multipleValues { @@ -577,7 +579,7 @@ extension PackageGraph.ResolvedModule { } } } - + /// Apply imparted settings to a ProjectModel.BuildSettings instance func applyImparted(to buildSettings: inout ProjectModel.BuildSettings) { // Apply imparted single value settings for all platforms @@ -590,7 +592,7 @@ extension PackageGraph.ResolvedModule { } } } - + // Apply imparted multiple value settings for all platforms for (platform, multipleValues) in impartedMultipleValueSettings { for (setting, values) in multipleValues { @@ -621,7 +623,7 @@ extension PackageGraph.ResolvedModule { let values: [String] let singleValueSetting: ProjectModel.BuildSettings.SingleValueSetting? let multipleValueSetting: ProjectModel.BuildSettings.MultipleValueSetting? - + switch declaration { case .LINK_FRAMEWORKS: singleValueSetting = nil @@ -714,13 +716,14 @@ extension SystemLibraryModule { return packageMetadata } - let brewPath = if FileManager.default.fileExists(atPath: "/opt/brew") { - "/opt/brew" // Legacy path for Homebrew. - } else if FileManager.default.fileExists(atPath: "/opt/homebrew") { - "/opt/homebrew" // Default path for Homebrew on Apple Silicon. - } else { - "/usr/local" // Fallback to default path for Homebrew. - } + let brewPath = + if FileManager.default.fileExists(atPath: "/opt/brew") { + "/opt/brew" // Legacy path for Homebrew. + } else if FileManager.default.fileExists(atPath: "/opt/homebrew") { + "/opt/homebrew" // Default path for Homebrew on Apple Silicon. + } else { + "/usr/local" // Fallback to default path for Homebrew. + } let emptyPkgConfig: (cFlags: [String], libs: [String]) = ([], []) @@ -930,7 +933,7 @@ extension TSCUtility.Version { // MARK: - Swift Build ProjectModel Helpers /// Helpful for logging. -extension ProjectModel.GUID: @retroactive CustomStringConvertible { +extension ProjectModel.GUID: @retroactive CustomStringConvertible { public var description: String { value } @@ -989,29 +992,29 @@ extension ProjectModel.BuildSettings { /// it must be one of the known platforms in `ProjectModel.BuildSettings.Platform`. } - extension ProjectModel.BuildSettings.Platform { enum Error: Swift.Error { case unknownPlatform(String) } init(from platform: PackageModel.Platform) throws { - self = switch platform { - case .macOS: .macOS - case .macCatalyst: .macCatalyst - case .iOS: .iOS - case .tvOS: .tvOS - case .watchOS: .watchOS - case .visionOS: .xrOS - case .driverKit: .driverKit - case .linux: .linux - case .android: .android - case .windows: .windows - case .wasi: .wasi - case .openbsd: .openbsd - case .freebsd: .freebsd - default: throw Error.unknownPlatform(platform.name) - } + self = + switch platform { + case .macOS: .macOS + case .macCatalyst: .macCatalyst + case .iOS: .iOS + case .tvOS: .tvOS + case .watchOS: .watchOS + case .visionOS: .xrOS + case .driverKit: .driverKit + case .linux: .linux + case .android: .android + case .windows: .windows + case .wasi: .wasi + case .openbsd: .openbsd + case .freebsd: .freebsd + default: throw Error.unknownPlatform(platform.name) + } } } @@ -1044,8 +1047,8 @@ extension ProjectModel.BuildSettings { // present. // The AppStore requires bumping the project version when ingesting new builds but that's for top-level apps // and not frameworks embedded inside it. - self[.MARKETING_VERSION] = "1.0" // Version - self[.CURRENT_PROJECT_VERSION] = "1" // Build + self[.MARKETING_VERSION] = "1.0" // Version + self[.CURRENT_PROJECT_VERSION] = "1" // Build } // Might set install path depending on build delegate. @@ -1106,7 +1109,7 @@ extension ObservabilityScope { let indentation = String(repeating: " ", count: Int(indent)) let message = "PIF: \(indentation)\(message)" - + let diagnostic = Diagnostic(severity: severity, message: message, metadata: metadata) self.emit(diagnostic) } @@ -1133,7 +1136,7 @@ public struct SourceLocation: Sendable { public init(_ file: StaticString, _ line: UInt) { precondition(file.description.hasContent) - + self.file = file self.line = line } @@ -1256,4 +1259,3 @@ extension UserDefaults { } } } - diff --git a/Sources/SwiftBuildSupport/PackagePIFBuilder+Plugins.swift b/Sources/SwiftBuildSupport/PackagePIFBuilder+Plugins.swift index f78bb1107fa..0c856d5f7d1 100644 --- a/Sources/SwiftBuildSupport/PackagePIFBuilder+Plugins.swift +++ b/Sources/SwiftBuildSupport/PackagePIFBuilder+Plugins.swift @@ -133,4 +133,3 @@ extension PackagePIFBuilder { } } } - diff --git a/Sources/SwiftBuildSupport/PackagePIFBuilder.swift b/Sources/SwiftBuildSupport/PackagePIFBuilder.swift index 53c7a428be8..21229410789 100644 --- a/Sources/SwiftBuildSupport/PackagePIFBuilder.swift +++ b/Sources/SwiftBuildSupport/PackagePIFBuilder.swift @@ -46,7 +46,7 @@ public final class PackagePIFBuilder { private let package: ResolvedPackage /// Contains the package declarative specification. - let packageManifest: PackageModel.Manifest // FIXME: Can't we just use `package.manifest` instead? —— Paulo + let packageManifest: PackageModel.Manifest // FIXME: Can't we just use `package.manifest` instead? —— Paulo /// The built PIF project object. public var pifProject: ProjectModel.Project { @@ -388,21 +388,22 @@ public final class PackagePIFBuilder { public var description: String { rawValue } init(from pifProductType: ProjectModel.Target.ProductType) { - self = switch pifProductType { - case .application: .application - case .staticArchive: .staticArchive - case .commonObject: .commonObject - case .dynamicLibrary: .dynamicLibrary - case .framework: .framework - case .executable: .executable - case .unitTest: .unitTest - case .swiftpmTestRunner: .unitTestRunner - case .bundle: .bundle - case .packageProduct: .packageProduct - case .hostBuildTool: fatalError("Unexpected hostBuildTool type") - @unknown default: - fatalError() - } + self = + switch pifProductType { + case .application: .application + case .staticArchive: .staticArchive + case .commonObject: .commonObject + case .dynamicLibrary: .dynamicLibrary + case .framework: .framework + case .executable: .executable + case .unitTest: .unitTest + case .swiftpmTestRunner: .unitTestRunner + case .bundle: .bundle + case .packageProduct: .packageProduct + case .hostBuildTool: fatalError("Unexpected hostBuildTool type") + @unknown default: + fatalError() + } } } @@ -411,8 +412,7 @@ public final class PackagePIFBuilder { public func build() throws -> [ModuleOrProduct] { self.log( .info, - "Building PIF project for package '\(self.package.identity)' " + - "(\(package.products.count) products, \(package.modules.count) modules)" + "Building PIF project for package '\(self.package.identity)' " + "(\(package.products.count) products, \(package.modules.count) modules)" ) var projectBuilder = PackagePIFProjectBuilder(createForPackage: package, builder: self) @@ -438,7 +438,7 @@ public final class PackagePIFBuilder { // self.log(.debug, "Processing \(package.products.count) products:") - + // For each of the **products** in the package we create a corresponding `PIFTarget` of the appropriate type. for product in self.package.products { switch product.type { @@ -467,7 +467,7 @@ public final class PackagePIFBuilder { try projectBuilder.makePluginProduct(product) case .macro: - break // TODO: Double-check what's going on here as we skip snippet modules too (rdar://147705448) + break // TODO: Double-check what's going on here as we skip snippet modules too (rdar://147705448) } } @@ -561,8 +561,8 @@ public final class PackagePIFBuilder { // We currently deliberately do not support Swift ObjC interface headers. settings[.SWIFT_INSTALL_OBJC_HEADER] = "NO" settings[.SWIFT_OBJC_INTERFACE_HEADER_NAME] = "" - - // rdar://47937899 (Don't try to link frameworks to object files) + + // rdar://47937899 (Don't try to link frameworks to object files) // - looks like this defaults to OTHER_LDFLAGS (via xcspec) which can result in linking frameworks to mh_objects which is unwanted. settings[.OTHER_LDRFLAGS] = [] diff --git a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift index a36ea1b48f2..2f84374a835 100644 --- a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift +++ b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift @@ -50,8 +50,7 @@ extension PackagePIFProjectBuilder { let pluginTarget = self.project[keyPath: pluginTargetKeyPath] log( .debug, - "Created target '\(pluginTarget.id)' of type " + - "\(pluginTarget.productType) and name '\(pluginTarget.name)'" + "Created target '\(pluginTarget.id)' of type " + "\(pluginTarget.productType) and name '\(pluginTarget.name)'" ) } @@ -65,7 +64,8 @@ extension PackagePIFProjectBuilder { // _other_ packages, but this should be resolved; see rdar://95467710. /* assert(moduleDependency.packageName == self.package.name) */ - let dependencyPlatformFilters = packageConditions + let dependencyPlatformFilters = + packageConditions .toPlatformFilter(toolsVersion: self.package.manifest.toolsVersion) switch moduleDependency.type { @@ -73,7 +73,8 @@ extension PackagePIFProjectBuilder { // For executable targets, add a build time dependency on the product. // FIXME: Maybe we should we do this at the libSwiftPM level. let moduleProducts = self.package.products.filter(\.isMainModuleProduct) - let productDependency = moduleDependency + let productDependency = + moduleDependency .productRepresentingDependencyOfBuildPlugin(in: moduleProducts) if let productDependency { @@ -110,7 +111,8 @@ extension PackagePIFProjectBuilder { buildSettings: &buildSettings ) { let dependencyGUID = productDependency.pifTargetGUID - let dependencyPlatformFilters = packageConditions + let dependencyPlatformFilters = + packageConditions .toPlatformFilter(toolsVersion: self.package.manifest.toolsVersion) self.project[keyPath: pluginTargetKeyPath].common.addDependency( @@ -185,8 +187,8 @@ extension PackagePIFProjectBuilder { self.builtModulesAndProducts.append(dynamicLibraryVariant) guard let pifTarget = staticLibrary.pifTarget, - let pifTargetKeyPath = self.project.findTarget(id: pifTarget.id), - let dynamicPifTarget = dynamicLibraryVariant.pifTarget + let pifTargetKeyPath = self.project.findTarget(id: pifTarget.id), + let dynamicPifTarget = dynamicLibraryVariant.pifTarget else { fatalError("Could not assign dynamic PIF target") } @@ -202,11 +204,12 @@ extension PackagePIFProjectBuilder { precondition(executableModule.type == .executable) guard self.package.manifest.toolsVersion >= .v5_5 else { return } - let inputResourceBundleName: String? = if mainModuleTargetNamesWithResources.contains(executableModule.name) { - resourceBundleName(forModuleName: executableModule.name) - } else { - nil - } + let inputResourceBundleName: String? = + if mainModuleTargetNamesWithResources.contains(executableModule.name) { + resourceBundleName(forModuleName: executableModule.name) + } else { + nil + } let (testableExecutableModule, _) = try buildSourceModule( executableModule, @@ -261,12 +264,13 @@ extension PackagePIFProjectBuilder { // For now wrapped in a static archive, since Swift Build can *not* yet produce a single .o as an output. // Macros are currently the only target type that requires explicit approval by users. - let approvedByUser: Bool = if desiredModuleType == .macro { - // Look up the current approval status in the underlying fingerprint storage. - pifBuilder.delegate.validateMacroFingerprint(for: sourceModule) == true - } else { - true - } + let approvedByUser: Bool = + if desiredModuleType == .macro { + // Look up the current approval status in the underlying fingerprint storage. + pifBuilder.delegate.validateMacroFingerprint(for: sourceModule) == true + } else { + true + } let sourceModuleTargetKeyPath = try self.project.addTarget { _ in ProjectModel.Target( @@ -281,8 +285,7 @@ extension PackagePIFProjectBuilder { let sourceModule = self.project[keyPath: sourceModuleTargetKeyPath] log( .debug, - "Created target '\(sourceModule.id)' of type '\(sourceModule.productType)' " + - "with name '\(sourceModule.name)' and product name '\(sourceModule.productName)'" + "Created target '\(sourceModule.id)' of type '\(sourceModule.productType)' " + "with name '\(sourceModule.name)' and product name '\(sourceModule.productName)'" ) } @@ -320,9 +323,10 @@ extension PackagePIFProjectBuilder { } // Find the PIF target for the resource bundle, if any. Otherwise fall back to the module. - let resourceBundleTargetKeyPath = self.resourceBundleTargetKeyPath( - forModuleName: sourceModule.name - ) ?? sourceModuleTargetKeyPath + let resourceBundleTargetKeyPath = + self.resourceBundleTargetKeyPath( + forModuleName: sourceModule.name + ) ?? sourceModuleTargetKeyPath // Add build tool commands to the resource bundle target. if desiredModuleType != .executable && desiredModuleType != .macro && addBuildToolPluginCommands { @@ -351,7 +355,7 @@ extension PackagePIFProjectBuilder { // Generate a module map file, if needed. var moduleMapFileContents = "" let generatedModuleMapDir = "$(GENERATED_MODULEMAP_DIR)" - let generatedModuleMapPath = try RelativePath(validating:"\(generatedModuleMapDir)/\(sourceModule.name).modulemap").pathString + let generatedModuleMapPath = try RelativePath(validating: "\(generatedModuleMapDir)/\(sourceModule.name).modulemap").pathString if sourceModule.usesSwift && desiredModuleType != .macro { // Generate ObjC compatibility header for Swift library targets. @@ -359,11 +363,11 @@ extension PackagePIFProjectBuilder { settings[.SWIFT_OBJC_INTERFACE_HEADER_NAME] = "\(sourceModule.name)-Swift.h" moduleMapFileContents = """ - module \(sourceModule.c99name) { - header "\(sourceModule.name)-Swift.h" - export * - } - """ + module \(sourceModule.c99name) { + header "\(sourceModule.name)-Swift.h" + export * + } + """ // We only need to impart this to C clients. impartedSettings[.OTHER_CFLAGS] = ["-fmodule-map-file=\(generatedModuleMapPath)", "$(inherited)"] } else { @@ -380,22 +384,22 @@ extension PackagePIFProjectBuilder { case .umbrellaHeader(let path): log(.debug, "\(package.name).\(sourceModule.name) generated umbrella header") moduleMapFileContents = """ - module \(sourceModule.c99name) { - umbrella header "\(path.escapedPathString)" - export * - } - """ + module \(sourceModule.c99name) { + umbrella header "\(path.escapedPathString)" + export * + } + """ // Pass the path of the module map up to all direct and indirect clients. impartedSettings[.OTHER_CFLAGS] = ["-fmodule-map-file=\(generatedModuleMapPath)", "$(inherited)"] impartedSettings[.OTHER_SWIFT_FLAGS] = ["-Xcc", "-fmodule-map-file=\(generatedModuleMapPath)", "$(inherited)"] case .umbrellaDirectory(let path): log(.debug, "\(package.name).\(sourceModule.name) generated umbrella directory") moduleMapFileContents = """ - module \(sourceModule.c99name) { - umbrella "\(path.escapedPathString)" - export * - } - """ + module \(sourceModule.c99name) { + umbrella "\(path.escapedPathString)" + export * + } + """ // Pass the path of the module map up to all direct and indirect clients. impartedSettings[.OTHER_CFLAGS] = ["-fmodule-map-file=\(generatedModuleMapPath)", "$(inherited)"] impartedSettings[.OTHER_SWIFT_FLAGS] = ["-Xcc", "-fmodule-map-file=\(generatedModuleMapPath)", "$(inherited)"] @@ -499,12 +503,12 @@ extension PackagePIFProjectBuilder { for platform in ProjectModel.BuildSettings.Platform.allCases { // darwin & freebsd switch platform { - case .macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .xrOS, .driverKit, .freebsd: - impartedSettings[.OTHER_LDFLAGS, platform] = ["-lc++", "$(inherited)"] - case .android, .linux, .wasi, .openbsd: - impartedSettings[.OTHER_LDFLAGS, platform] = ["-lstdc++", "$(inherited)"] - case .windows, ._iOSDevice: - break + case .macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .xrOS, .driverKit, .freebsd: + impartedSettings[.OTHER_LDFLAGS, platform] = ["-lc++", "$(inherited)"] + case .android, .linux, .wasi, .openbsd: + impartedSettings[.OTHER_LDFLAGS, platform] = ["-lstdc++", "$(inherited)"] + case .windows, ._iOSDevice: + break } } } @@ -596,7 +600,7 @@ extension PackagePIFProjectBuilder { // We have an explicit resource bundle via Bundle.module. // #bundle should call into that. settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS].lazilyInitializeAndMutate(initialValue: ["$(inherited)"]) { $0.append("SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE") } - } // else we won't set either of those and just let #bundle point to the same bundle as the source code. + } // else we won't set either of those and just let #bundle point to the same bundle as the source code. } if desiredModuleType == .macro { @@ -617,7 +621,8 @@ extension PackagePIFProjectBuilder { // _other_ packages, but this should be resolved; see rdar://95467710. /* assert(moduleDependency.packageName == self.package.name) */ - let dependencyPlatformFilters = packageConditions + let dependencyPlatformFilters = + packageConditions .toPlatformFilter(toolsVersion: self.package.manifest.toolsVersion) switch moduleDependency.type { @@ -625,7 +630,8 @@ extension PackagePIFProjectBuilder { // Always depend on product of executable targets (if available). // FIXME: Maybe we should we do this at the libSwiftPM level. let moduleMainProducts = self.package.products.filter(\.isMainModuleProduct) - if let product = moduleDependency + if let product = + moduleDependency .productRepresentingDependencyOfBuildPlugin(in: moduleMainProducts) { self.project[keyPath: sourceModuleTargetKeyPath].common.addDependency( @@ -705,7 +711,8 @@ extension PackagePIFProjectBuilder { product: productDependency.underlying, buildSettings: &settings ) { - let dependencyPlatformFilters = packageConditions + let dependencyPlatformFilters = + packageConditions .toPlatformFilter(toolsVersion: self.package.manifest.toolsVersion) let shouldLinkProduct = shouldLinkProduct && productDependency.isLinkable @@ -788,13 +795,14 @@ extension PackagePIFProjectBuilder { PackagePIFBuilder.LinkedPackageBinary(dependency: $0, package: self.package) } - let productOrModuleType: PackagePIFBuilder.ModuleOrProductType = if desiredModuleType == .dynamicLibrary { - pifBuilder.createDylibForDynamicProducts ? .dynamicLibrary : .framework - } else if desiredModuleType == .macro { - .macro - } else { - .module - } + let productOrModuleType: PackagePIFBuilder.ModuleOrProductType = + if desiredModuleType == .dynamicLibrary { + pifBuilder.createDylibForDynamicProducts ? .dynamicLibrary : .framework + } else if desiredModuleType == .macro { + .macro + } else { + .module + } let moduleOrProduct = PackagePIFBuilder.ModuleOrProduct( type: productOrModuleType, @@ -842,8 +850,7 @@ extension PackagePIFProjectBuilder { // Impart the header search path to all direct and indirect clients. var impartedSettings = ProjectModel.BuildSettings() - impartedSettings[.OTHER_CFLAGS] = ["-fmodule-map-file=\(systemLibrary.modulemapFileAbsolutePath)"] + - pkgConfig.cFlags.prepending("$(inherited)") + impartedSettings[.OTHER_CFLAGS] = ["-fmodule-map-file=\(systemLibrary.modulemapFileAbsolutePath)"] + pkgConfig.cFlags.prepending("$(inherited)") impartedSettings[.OTHER_LDFLAGS] = pkgConfig.libs.prepending("$(inherited)") impartedSettings[.OTHER_SWIFT_FLAGS] = ["-Xcc"] + impartedSettings[.OTHER_CFLAGS]! log(.debug, indent: 1, "Added '\(systemLibrary.path.pathString)' to imparted HEADER_SEARCH_PATHS") diff --git a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift index e7c75b928d6..9fc80f8d340 100644 --- a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift +++ b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift @@ -84,8 +84,7 @@ extension PackagePIFProjectBuilder { let mainModuleTarget = self.project[keyPath: mainModuleTargetKeyPath] log( .debug, - "Created target '\(mainModuleTarget.id)' of type '\(mainModuleTarget.productType)' " + - "with name '\(mainModuleTarget.name)' and product name '\(mainModuleTarget.productName)'" + "Created target '\(mainModuleTarget.id)' of type '\(mainModuleTarget.productType)' " + "with name '\(mainModuleTarget.name)' and product name '\(mainModuleTarget.productName)'" ) } @@ -123,7 +122,7 @@ extension PackagePIFProjectBuilder { settings[.LD_RUNPATH_SEARCH_PATHS] = [ "$(RPATH_ORIGIN)/Frameworks", "$(RPATH_ORIGIN)/../Frameworks", - "$(inherited)" + "$(inherited)", ] } settings[.GENERATE_INFOPLIST_FILE] = "YES" @@ -364,7 +363,8 @@ extension PackagePIFProjectBuilder { let dependencyId = moduleDependency.pifTargetGUID self.project[keyPath: mainModuleTargetKeyPath].common.addDependency( on: dependencyId, - platformFilters: packageConditions + platformFilters: + packageConditions .toPlatformFilter(toolsVersion: package.manifest.toolsVersion), linkProduct: false ) @@ -374,7 +374,8 @@ extension PackagePIFProjectBuilder { let dependencyId = moduleDependency.pifTargetGUID self.project[keyPath: mainModuleTargetKeyPath].common.addDependency( on: dependencyId, - platformFilters: packageConditions + platformFilters: + packageConditions .toPlatformFilter(toolsVersion: package.manifest.toolsVersion), linkProduct: false ) @@ -384,7 +385,8 @@ extension PackagePIFProjectBuilder { if product.type == .test { self.project[keyPath: mainModuleTargetKeyPath].common.addDependency( on: moduleDependency.pifTargetGUID(suffix: .testable), - platformFilters: packageConditions + platformFilters: + packageConditions .toPlatformFilter(toolsVersion: package.manifest.toolsVersion), linkProduct: true ) @@ -420,7 +422,8 @@ extension PackagePIFProjectBuilder { let productDependencyGUID = productDependency.pifTargetGUID self.project[keyPath: mainModuleTargetKeyPath].common.addDependency( on: productDependencyGUID, - platformFilters: packageConditions + platformFilters: + packageConditions .toPlatformFilter(toolsVersion: package.manifest.toolsVersion), linkProduct: false ) @@ -433,7 +436,8 @@ extension PackagePIFProjectBuilder { let moduleDependencyGUID = moduleDependency.pifTargetGUID(suffix: .testable) self.project[keyPath: mainModuleTargetKeyPath].common.addDependency( on: moduleDependencyGUID, - platformFilters: packageConditions + platformFilters: + packageConditions .toPlatformFilter(toolsVersion: package.manifest.toolsVersion), // Only link the testable version of executables which use Swift, as we do not currently support renaming entrypoints written in other languages. linkProduct: moduleDependency.usesSwift @@ -446,7 +450,8 @@ extension PackagePIFProjectBuilder { let dependencyGUID = moduleDependency.pifTargetGUID self.project[keyPath: mainModuleTargetKeyPath].common.addDependency( on: dependencyGUID, - platformFilters: packageConditions + platformFilters: + packageConditions .toPlatformFilter(toolsVersion: package.manifest.toolsVersion), linkProduct: shouldLinkProduct ) @@ -477,7 +482,7 @@ extension PackagePIFProjectBuilder { // Apply target-specific build settings defined in the manifest. let allBuildSettings = mainModule.computeAllBuildSettings(observabilityScope: pifBuilder.observabilityScope) - + // Apply settings using the convenience methods allBuildSettings.apply(to: &debugSettings, for: .debug) allBuildSettings.apply(to: &releaseSettings, for: .release) @@ -568,8 +573,8 @@ extension PackagePIFProjectBuilder { self.builtModulesAndProducts.append(dynamicLibraryVariant) guard let pifTarget = library.pifTarget, - let pifTargetKeyPath = self.project.findTarget(id: pifTarget.id), - let dynamicPifTarget = dynamicLibraryVariant.pifTarget + let pifTargetKeyPath = self.project.findTarget(id: pifTarget.id), + let dynamicPifTarget = dynamicLibraryVariant.pifTarget else { fatalError("Could not assign dynamic PIF target") } @@ -622,8 +627,7 @@ extension PackagePIFProjectBuilder { let librayTarget = self.project[keyPath: libraryUmbrellaTargetKeyPath] log( .debug, - "Created target '\(librayTarget.id)' of type '\(librayTarget.productType)' with " + - "name '\(librayTarget.name)' and product name '\(librayTarget.productName)'" + "Created target '\(librayTarget.id)' of type '\(librayTarget.productType)' with " + "name '\(librayTarget.name)' and product name '\(librayTarget.productName)'" ) } @@ -704,8 +708,7 @@ extension PackagePIFProjectBuilder { ) // If the given package is a root package or it is used via a branch/revision, we allow unsafe flags. - let implicitlyAllowAllUnsafeFlags = pifBuilder.delegate.isBranchOrRevisionBased || - pifBuilder.delegate.isUserManaged + let implicitlyAllowAllUnsafeFlags = pifBuilder.delegate.isBranchOrRevisionBased || pifBuilder.delegate.isUserManaged let recordUsesUnsafeFlags = try !implicitlyAllowAllUnsafeFlags && product.usesUnsafeFlags settings[.USES_SWIFTPM_UNSAFE_FLAGS] = recordUsesUnsafeFlags ? "YES" : "NO" @@ -746,7 +749,8 @@ extension PackagePIFProjectBuilder { let dependencyId = moduleDependency.pifTargetGUID self.project[keyPath: libraryUmbrellaTargetKeyPath].common.addDependency( on: dependencyId, - platformFilters: packageConditions + platformFilters: + packageConditions .toPlatformFilter(toolsVersion: package.manifest.toolsVersion), linkProduct: false ) @@ -762,12 +766,14 @@ extension PackagePIFProjectBuilder { if moduleDependency.isExecutable { let mainModuleProducts = package.products.filter(\.isMainModuleProduct) - if let product = moduleDependency + if let product = + moduleDependency .productRepresentingDependencyOfBuildPlugin(in: mainModuleProducts) { self.project[keyPath: libraryUmbrellaTargetKeyPath].common.addDependency( on: product.pifTargetGUID, - platformFilters: packageConditions + platformFilters: + packageConditions .toPlatformFilter(toolsVersion: package.manifest.toolsVersion), linkProduct: false ) @@ -802,7 +808,8 @@ extension PackagePIFProjectBuilder { let shouldLinkProduct = productDependency.isLinkable self.project[keyPath: libraryUmbrellaTargetKeyPath].common.addDependency( on: productDependency.pifTargetGUID, - platformFilters: packageConditions + platformFilters: + packageConditions .toPlatformFilter(toolsVersion: package.manifest.toolsVersion), linkProduct: shouldLinkProduct ) @@ -817,9 +824,9 @@ extension PackagePIFProjectBuilder { // For *registry* packages, vend any registry release metadata to the build system. if let metadata = package.registryMetadata, - let signature = metadata.signature, - let version = pifBuilder.packageDisplayVersion, - case RegistryReleaseMetadata.Source.registry(let url) = metadata.source + let signature = metadata.signature, + let version = pifBuilder.packageDisplayVersion, + case RegistryReleaseMetadata.Source.registry(let url) = metadata.source { let signatureData = PackageRegistrySignature( packageIdentity: package.identity.description, @@ -847,12 +854,13 @@ extension PackagePIFProjectBuilder { PackagePIFBuilder.LinkedPackageBinary(module: $0, package: self.package) } - let moduleOrProductType: PackagePIFBuilder.ModuleOrProductType = switch product.libraryType { - case .dynamic: - pifBuilder.createDylibForDynamicProducts ? .dynamicLibrary : .framework - default: - .staticArchive - } + let moduleOrProductType: PackagePIFBuilder.ModuleOrProductType = + switch product.libraryType { + case .dynamic: + pifBuilder.createDylibForDynamicProducts ? .dynamicLibrary : .framework + default: + .staticArchive + } return PackagePIFBuilder.ModuleOrProduct( type: moduleOrProductType, @@ -885,8 +893,7 @@ extension PackagePIFProjectBuilder { let systemLibraryTarget = self.project[keyPath: systemLibraryTargetKeyPath] log( .debug, - "Created target '\(systemLibraryTarget.id)' of type '\(systemLibraryTarget.productType)' " + - "with name '\(systemLibraryTarget.name)' and product name '\(systemLibraryTarget.productName)'" + "Created target '\(systemLibraryTarget.id)' of type '\(systemLibraryTarget.productType)' " + "with name '\(systemLibraryTarget.name)' and product name '\(systemLibraryTarget.productName)'" ) } @@ -997,7 +1004,7 @@ extension PackagePIFProjectBuilder { let guid = PackagePIFBuilder.targetGUID(forModuleName: moduleName) let testRunnerTargetKeyPath = try self.project.addTarget { _ in - ProjectModel.Target ( + ProjectModel.Target( id: guid, productType: .swiftpmTestRunner, name: name, @@ -1024,7 +1031,7 @@ extension PackagePIFProjectBuilder { if pifBuilder.addLocalRpaths { settings[.LD_RUNPATH_SEARCH_PATHS] = [ "$(inherited)", - "$(RPATH_ORIGIN)" + "$(RPATH_ORIGIN)", ] } @@ -1100,4 +1107,3 @@ private struct PackageRegistrySignature: Encodable { let source: Source let formatVersion = 2 } - diff --git a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift index 6684a2e5e9e..c55d30d22d7 100644 --- a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift +++ b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift @@ -164,11 +164,13 @@ struct PackagePIFProjectBuilder { generatedResourceFiles: [String] ) throws -> (PackagePIFBuilder.EmbedResourcesResult, PackagePIFBuilder.ModuleOrProduct?) { if module.resources.isEmpty && generatedResourceFiles.isEmpty { - return (PackagePIFBuilder.EmbedResourcesResult( - bundleName: nil, - shouldGenerateBundleAccessor: false, - shouldGenerateEmbedInCodeAccessor: false - ), nil) + return ( + PackagePIFBuilder.EmbedResourcesResult( + bundleName: nil, + shouldGenerateBundleAccessor: false, + shouldGenerateEmbedInCodeAccessor: false + ), nil + ) } let bundleName = self.resourceBundleName(forModuleName: module.name) @@ -201,8 +203,7 @@ struct PackagePIFProjectBuilder { self.log( .debug, indent: 1, - "Created target '\(resourcesTarget.id)' of type '\(resourcesTarget.productType)' " + - "with name '\(resourcesTarget.name)' and product name '\(resourcesTarget.productName)'" + "Created target '\(resourcesTarget.id)' of type '\(resourcesTarget.productType)' " + "with name '\(resourcesTarget.name)' and product name '\(resourcesTarget.productName)'" ) var settings: ProjectModel.BuildSettings = self.package.underlying.packageBaseBuildSettings @@ -266,7 +267,7 @@ struct PackagePIFProjectBuilder { // If resourceBundleTarget is nil, we add resources to the sourceModuleTarget instead. let targetForResourcesKeyPath: WritableKeyPath = resourceBundleTargetKeyPath ?? sourceModuleTargetKeyPath - + // Generated resources get a default treatment for rule and localization. let generatedResources = generatedResourceFiles.compactMap { PackagePIFBuilder.Resource(path: $0, rule: .process(localization: nil)) @@ -354,7 +355,7 @@ struct PackagePIFProjectBuilder { } else { resourceBundleTargetName = nil } - + return PackagePIFBuilder.EmbedResourcesResult( bundleName: resourceBundleTargetName, shouldGenerateBundleAccessor: shouldGenerateBundleAccessor, @@ -544,7 +545,7 @@ struct PackagePIFProjectBuilder { FileRuleDescription( rule: .processResource(localization: .none), toolsVersion: .v5_7, - fileTypes: ["rkassets"] // visionOS + fileTypes: ["rkassets"] // visionOS ), ] @@ -566,4 +567,3 @@ struct PackagePIFProjectBuilder { !self.dynamicLibraryProductNames.contains(targetName) } } - diff --git a/Sources/SwiftBuildSupport/SwiftBuildSystem.swift b/Sources/SwiftBuildSupport/SwiftBuildSystem.swift index bf0e98161cf..77dbccd8610 100644 --- a/Sources/SwiftBuildSupport/SwiftBuildSystem.swift +++ b/Sources/SwiftBuildSupport/SwiftBuildSystem.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import Dispatch import class Foundation.FileManager import class Foundation.JSONEncoder @@ -21,8 +20,7 @@ import PackageGraph import PackageModel import PackageLoading -@_spi(SwiftPMInternal) -import SPMBuildCore +@_spi(SwiftPMInternal) import SPMBuildCore import class Basics.AsyncProcess import func TSCBasic.memoize @@ -37,7 +35,6 @@ import Foundation import SWBBuildService import SwiftBuild - struct SessionFailedError: Error { var error: Error var diagnostics: [SwiftBuild.SwiftBuildMessage.DiagnosticInfo] @@ -66,13 +63,14 @@ public func createSession( name: String, toolchainPath: Basics.AbsolutePath, packageManagerResourcesDirectory: Basics.AbsolutePath? -) async throws-> (SWBBuildServiceSession, [SwiftBuildMessage.DiagnosticInfo]) { +) async throws -> (SWBBuildServiceSession, [SwiftBuildMessage.DiagnosticInfo]) { // SWIFT_EXEC and SWIFT_EXEC_MANIFEST may need to be overridden in debug scenarios in order to pick up Open Source toolchains - let sessionResult = if toolchainPath.components.contains(where: { $0.hasSuffix(".app") }) { - await service.createSession(name: name, developerPath: nil, resourceSearchPaths: packageManagerResourcesDirectory.map { [$0.pathString] } ?? [], cachePath: nil, inferiorProductsPath: nil, environment: nil) - } else { - await service.createSession(name: name, swiftToolchainPath: toolchainPath.pathString, resourceSearchPaths: packageManagerResourcesDirectory.map { [$0.pathString] } ?? [], cachePath: nil, inferiorProductsPath: nil, environment: nil) - } + let sessionResult = + if toolchainPath.components.contains(where: { $0.hasSuffix(".app") }) { + await service.createSession(name: name, developerPath: nil, resourceSearchPaths: packageManagerResourcesDirectory.map { [$0.pathString] } ?? [], cachePath: nil, inferiorProductsPath: nil, environment: nil) + } else { + await service.createSession(name: name, swiftToolchainPath: toolchainPath.pathString, resourceSearchPaths: packageManagerResourcesDirectory.map { [$0.pathString] } ?? [], cachePath: nil, inferiorProductsPath: nil, environment: nil) + } switch sessionResult { case (.success(let session), let diagnostics): return (session, diagnostics) @@ -118,14 +116,16 @@ private final class PlanningOperationDelegate: SWBPlanningOperationDelegate, Sen ) async -> SWBProvisioningTaskInputs { let identity = provisioningSourceData.signingCertificateIdentifier if identity == "-" { - let signedEntitlements = provisioningSourceData.entitlementsDestination == "Signature" + let signedEntitlements = + provisioningSourceData.entitlementsDestination == "Signature" ? provisioningSourceData.productTypeEntitlements.merging( ["application-identifier": .plString(provisioningSourceData.bundleIdentifier)], uniquingKeysWith: { _, new in new } ).merging(provisioningSourceData.projectEntitlements ?? [:], uniquingKeysWith: { _, new in new }) : [:] - let simulatedEntitlements = provisioningSourceData.entitlementsDestination == "__entitlements" + let simulatedEntitlements = + provisioningSourceData.entitlementsDestination == "__entitlements" ? provisioningSourceData.productTypeEntitlements.merging( ["application-identifier": .plString(provisioningSourceData.bundleIdentifier)], uniquingKeysWith: { _, new in new } @@ -158,8 +158,8 @@ private final class PlanningOperationDelegate: SWBPlanningOperationDelegate, Sen identityHash: "-", errors: [ [ - "description": "unable to supply accurate provisioning inputs for CODE_SIGN_IDENTITY=\(identity)\"", - ], + "description": "unable to supply accurate provisioning inputs for CODE_SIGN_IDENTITY=\(identity)\"" + ] ] ) } @@ -266,7 +266,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { func getUniqueBuildSettingsIncludingDependencies(of targetGuid: [SWBConfiguredTarget], buildSettings: [String]) async throws -> Set { let dependencyGraph = try await session.computeDependencyGraph( - targetGUIDs: request.configuredTargets.map { SWBTargetGUID(rawValue: $0.guid)}, + targetGUIDs: request.configuredTargets.map { SWBTargetGUID(rawValue: $0.guid) }, buildParameters: request.parameters, includeImplicitDependencies: true, ) @@ -309,9 +309,11 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { // The graph should have the REPL product. assert(graph.product(for: replProductName) != nil) - let arguments = ["repl", "-l\(replProductName)"] + includePaths.map { - "-I\($0)" - } + let arguments = + ["repl", "-l\(replProductName)"] + + includePaths.map { + "-I\($0)" + } self.outputStream.send("Done.\n") return arguments @@ -447,13 +449,15 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { let pluginProducts = package.products.filter { $0.modules.contains(id: pluginModule.id) } - allPlugins.append(try PluginBuildDescription( - module: pluginModule, - products: pluginProducts, - package: package, - toolsVersion: toolsVersion, - fileSystem: fileSystem - )) + allPlugins.append( + try PluginBuildDescription( + module: pluginModule, + products: pluginProducts, + package: package, + toolsVersion: toolsVersion, + fileSystem: fileSystem + ) + ) } let pluginsToCompile: [PluginBuildDescription] @@ -463,10 +467,10 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { pluginsToCompile = allPlugins continueBuilding = true case .product(let productName, _): - pluginsToCompile = allPlugins.filter{ $0.productNames.contains(productName) } + pluginsToCompile = allPlugins.filter { $0.productNames.contains(productName) } continueBuilding = pluginsToCompile.isEmpty case .target(let targetName, _): - pluginsToCompile = allPlugins.filter{ $0.moduleName == targetName } + pluginsToCompile = allPlugins.filter { $0.moduleName == targetName } continueBuilding = pluginsToCompile.isEmpty } @@ -478,7 +482,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { self.observabilityScope = observabilityScope } - func willCompilePlugin(commandLine: [String], environment: [String: String]) { } + func willCompilePlugin(commandLine: [String], environment: [String: String]) {} func didCompilePlugin(result: PluginCompilationResult) { if !result.compilerOutput.isEmpty && !result.succeeded { @@ -490,7 +494,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { failed = !result.succeeded } - func skippedCompilingPlugin(cachedResult: PluginCompilationResult) { } + func skippedCompilingPlugin(cachedResult: PluginCompilationResult) {} } // Compile any plugins we ended up with. If any of them fails, it will @@ -632,31 +636,35 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { case .didUpdateProgress(let progressInfo): var step = Int(progressInfo.percentComplete) if step < 0 { step = 0 } - let message = if let targetName = progressInfo.targetName { - "\(targetName) \(progressInfo.message)" - } else { - "\(progressInfo.message)" - } + let message = + if let targetName = progressInfo.targetName { + "\(targetName) \(progressInfo.message)" + } else { + "\(progressInfo.message)" + } progressAnimation.update(step: step, total: 100, text: message) self.delegate?.buildSystem(self, didUpdateTaskProgress: message) case .diagnostic(let info): func emitInfoAsDiagnostic(info: SwiftBuildMessage.DiagnosticInfo) { - let fixItsDescription = if info.fixIts.hasContent { - ": " + info.fixIts.map { String(describing: $0) }.joined(separator: ", ") - } else { - "" - } - let message = if let locationDescription = info.location.userDescription { - "\(locationDescription) \(info.message)\(fixItsDescription)" - } else { - "\(info.message)\(fixItsDescription)" - } - let severity: Diagnostic.Severity = switch info.kind { - case .error: .error - case .warning: .warning - case .note: .info - case .remark: .debug - } + let fixItsDescription = + if info.fixIts.hasContent { + ": " + info.fixIts.map { String(describing: $0) }.joined(separator: ", ") + } else { + "" + } + let message = + if let locationDescription = info.location.userDescription { + "\(locationDescription) \(info.message)\(fixItsDescription)" + } else { + "\(info.message)\(fixItsDescription)" + } + let severity: Diagnostic.Severity = + switch info.kind { + case .error: .error + case .warning: .warning + case .note: .info + case .remark: .debug + } self.observabilityScope.emit(severity: severity, message: "\(message)\n") for childDiagnostic in info.childDiagnostics { @@ -694,13 +702,16 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { let targetInfo = try buildState.target(for: startedInfo) self.delegate?.buildSystem(self, didFinishCommand: BuildSystemCommand(startedInfo, targetInfo: targetInfo)) if let targetName = targetInfo?.targetName { - serializedDiagnosticPathsByTargetName[targetName, default: []].append(contentsOf: startedInfo.serializedDiagnosticsPaths.compactMap { - try? Basics.AbsolutePath(validating: $0.pathString) - }) + serializedDiagnosticPathsByTargetName[targetName, default: []].append( + contentsOf: startedInfo.serializedDiagnosticsPaths.compactMap { + try? Basics.AbsolutePath(validating: $0.pathString) + } + ) } if self.buildParameters.outputParameters.enableTaskBacktraces { if let id = SWBBuildOperationBacktraceFrame.Identifier(taskSignatureData: Data(startedInfo.taskSignature.utf8)), - let backtrace = SWBTaskBacktrace(from: id, collectedFrames: buildState.collectedBacktraceFrames) { + let backtrace = SWBTaskBacktrace(from: id, collectedFrames: buildState.collectedBacktraceFrames) + { let formattedBacktrace = backtrace.renderTextualRepresentation() if !formattedBacktrace.isEmpty { self.observabilityScope.emit(info: "Task backtrace:\n\(formattedBacktrace)") @@ -716,9 +727,9 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { case .planningOperationStarted, .planningOperationCompleted, .reportBuildDescription, .reportPathMap, .preparedForIndex, .buildStarted, .preparationComplete, .targetUpToDate, .targetComplete, .taskUpToDate: break case .buildDiagnostic, .targetDiagnostic, .taskDiagnostic: - break // deprecated + break // deprecated case .buildOutput, .targetOutput, .taskOutput: - break // deprecated + break // deprecated @unknown default: break } @@ -775,26 +786,30 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { guard let artifactInfo = target.artifactInfo else { return nil } - let kind: PluginInvocationBuildResult.BuiltArtifact.Kind = switch artifactInfo.kind { - case .executable: - .executable - case .staticLibrary: - .staticLibrary - case .dynamicLibrary: - .dynamicLibrary - case .framework: - // We treat frameworks as dylibs here, but the plugin API should grow to accomodate more product types - .dynamicLibrary - } + let kind: PluginInvocationBuildResult.BuiltArtifact.Kind = + switch artifactInfo.kind { + case .executable: + .executable + case .staticLibrary: + .staticLibrary + case .dynamicLibrary: + .dynamicLibrary + case .framework: + // We treat frameworks as dylibs here, but the plugin API should grow to accomodate more product types + .dynamicLibrary + } var name = target.name // FIXME: We need a better way to map between SwiftPM target/product names and PIF target names if pifTargetName.hasSuffix("-product") { name = String(name.dropLast(8)) } - return (name, .init( - path: artifactInfo.path, - kind: kind - )) + return ( + name, + .init( + path: artifactInfo.path, + kind: kind + ) + ) } } else { self.observabilityScope.emit(error: "failed to compute built artifacts list") @@ -866,7 +881,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { var verboseFlag: [String] = [] if self.logLevel == .debug { - verboseFlag = ["-v"] // Clang's verbose flag + verboseFlag = ["-v"] // Clang's verbose flag } // Generate a table of any overriding build settings. @@ -949,31 +964,24 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { } settings["LIBRARY_SEARCH_PATHS"] = try "$(inherited) \(buildParameters.toolchain.toolchainLibDir.pathString)" - settings["OTHER_CFLAGS"] = ( - verboseFlag + - ["$(inherited)"] - + buildParameters.toolchain.extraFlags.cCompilerFlags.map { $0.shellEscaped() } - + buildParameters.flags.cCompilerFlags.map { $0.shellEscaped() } - ).joined(separator: " ") - settings["OTHER_CPLUSPLUSFLAGS"] = ( - verboseFlag + - ["$(inherited)"] - + buildParameters.toolchain.extraFlags.cxxCompilerFlags.map { $0.shellEscaped() } - + buildParameters.flags.cxxCompilerFlags.map { $0.shellEscaped() } - ).joined(separator: " ") - settings["OTHER_SWIFT_FLAGS"] = ( - verboseFlag + - ["$(inherited)"] - + buildParameters.toolchain.extraFlags.swiftCompilerFlags.map { $0.shellEscaped() } - + buildParameters.flags.swiftCompilerFlags.map { $0.shellEscaped() } - ).joined(separator: " ") - - settings["OTHER_LDFLAGS"] = ( - verboseFlag + // clang will be invoked to link so the verbose flag is valid for it - ["$(inherited)"] - + buildParameters.toolchain.extraFlags.linkerFlags.asSwiftcLinkerFlags().map { $0.shellEscaped() } - + buildParameters.flags.linkerFlags.asSwiftcLinkerFlags().map { $0.shellEscaped() } - ).joined(separator: " ") + settings["OTHER_CFLAGS"] = + (verboseFlag + ["$(inherited)"] + + buildParameters.toolchain.extraFlags.cCompilerFlags.map { $0.shellEscaped() } + + buildParameters.flags.cCompilerFlags.map { $0.shellEscaped() }).joined(separator: " ") + settings["OTHER_CPLUSPLUSFLAGS"] = + (verboseFlag + ["$(inherited)"] + + buildParameters.toolchain.extraFlags.cxxCompilerFlags.map { $0.shellEscaped() } + + buildParameters.flags.cxxCompilerFlags.map { $0.shellEscaped() }).joined(separator: " ") + settings["OTHER_SWIFT_FLAGS"] = + (verboseFlag + ["$(inherited)"] + + buildParameters.toolchain.extraFlags.swiftCompilerFlags.map { $0.shellEscaped() } + + buildParameters.flags.swiftCompilerFlags.map { $0.shellEscaped() }).joined(separator: " ") + + settings["OTHER_LDFLAGS"] = + (verboseFlag // clang will be invoked to link so the verbose flag is valid for it + + ["$(inherited)"] + + buildParameters.toolchain.extraFlags.linkerFlags.asSwiftcLinkerFlags().map { $0.shellEscaped() } + + buildParameters.flags.linkerFlags.asSwiftcLinkerFlags().map { $0.shellEscaped() }).joined(separator: " ") // Optionally also set the list of architectures to build for. if let architectures = buildParameters.architectures, !architectures.isEmpty { @@ -1024,9 +1032,9 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { // up earlier in this method. #if os(Windows) - let ddPathPrefix = derivedDataPath.pathString.replacingOccurrences(of: "\\", with: "/") + let ddPathPrefix = derivedDataPath.pathString.replacingOccurrences(of: "\\", with: "/") #else - let ddPathPrefix = derivedDataPath.pathString + let ddPathPrefix = derivedDataPath.pathString #endif let arenaInfo = SWBArenaInfo( @@ -1202,9 +1210,9 @@ extension String { /// back-slashes. fileprivate func shellEscaped() -> String { #if os(Windows) - return self.spm_shellEscaped().replacingOccurrences(of: "\\", with: "/") + return self.spm_shellEscaped().replacingOccurrences(of: "\\", with: "/") #else - return self.spm_shellEscaped() + return self.spm_shellEscaped() #endif } } @@ -1223,13 +1231,13 @@ fileprivate extension SwiftBuild.SwiftBuildMessage.DiagnosticInfo.Location { case .none: return path } - + case .buildSettings(let names): return names.joined(separator: ", ") - + case .buildFiles(let buildFiles, let targetGUID): return "\(targetGUID): " + buildFiles.map { String(describing: $0) }.joined(separator: ", ") - + case .unknown: return nil } diff --git a/Sources/SwiftFixIt/SwiftFixIt.swift b/Sources/SwiftFixIt/SwiftFixIt.swift index 3001affe36e..0e10267536f 100644 --- a/Sources/SwiftFixIt/SwiftFixIt.swift +++ b/Sources/SwiftFixIt/SwiftFixIt.swift @@ -23,8 +23,7 @@ import protocol SwiftDiagnostics.FixItMessage import struct SwiftDiagnostics.GroupedDiagnostics import struct SwiftDiagnostics.MessageID -@_spi(FixItApplier) -import enum SwiftIDEUtils.FixItApplier +@_spi(FixItApplier) import enum SwiftIDEUtils.FixItApplier import struct SwiftParser.Parser @@ -159,7 +158,7 @@ private struct PrimaryDiagnosticFilter: ~Copyable { // diagnostic appears in is in any of them. if !self.excludedSourceDirectories.isEmpty { if let sourceFilePath = try? AbsolutePath(validating: location.filename), - self.excludedSourceDirectories.contains(where: sourceFilePath.isDescendant(of:)) + self.excludedSourceDirectories.contains(where: sourceFilePath.isDescendant(of:)) { return true } @@ -203,7 +202,7 @@ private struct PrimaryDiagnosticFilter: ~Copyable { } /// The backing API for `SwiftFixitCommand`. -package struct SwiftFixIt /*: ~Copyable */ { // TODO: Crashes with ~Copyable +package struct SwiftFixIt /*: ~Copyable */ { // TODO: Crashes with ~Copyable private typealias DiagnosticsPerFile = [SourceFile: [SwiftDiagnostics.Diagnostic]] private let fileSystem: any FileSystem @@ -255,7 +254,7 @@ package struct SwiftFixIt /*: ~Copyable */ { // TODO: Crashes with ~Copyable diagnostics.formIndex(after: &nextPrimaryIndex) } while nextPrimaryIndex != diagnostics.endIndex && diagnostics[nextPrimaryIndex].isNote - let primaryDiagnosticWithNotes = diagnostics[currentPrimaryIndex ..< nextPrimaryIndex] + let primaryDiagnosticWithNotes = diagnostics[currentPrimaryIndex.. [Command] { - // This plugin only runs for package targets that can have source files. - guard let sourceFiles = target.sourceModule?.sourceFiles else { return [] } - - // Find the code generator tool to run (replace this with the actual one). - let generatorTool = try context.tool(named: "my-code-generator") - - // Construct a build command for each source file with a particular suffix. - return sourceFiles.map(\\.url).compactMap { - createBuildCommand(for: $0, in: context.pluginWorkDirectoryURL, with: generatorTool.url) + struct \(typeName): BuildToolPlugin { + /// Entry point for creating build commands for targets in Swift packages. + func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] { + // This plugin only runs for package targets that can have source files. + guard let sourceFiles = target.sourceModule?.sourceFiles else { return [] } + + // Find the code generator tool to run (replace this with the actual one). + let generatorTool = try context.tool(named: "my-code-generator") + + // Construct a build command for each source file with a particular suffix. + return sourceFiles.map(\\.url).compactMap { + createBuildCommand(for: $0, in: context.pluginWorkDirectoryURL, with: generatorTool.url) + } } } - } - #if canImport(XcodeProjectPlugin) - import XcodeProjectPlugin + #if canImport(XcodeProjectPlugin) + import XcodeProjectPlugin - extension \(typeName): XcodeBuildToolPlugin { - // Entry point for creating build commands for targets in Xcode projects. - func createBuildCommands(context: XcodePluginContext, target: XcodeTarget) throws -> [Command] { - // Find the code generator tool to run (replace this with the actual one). - let generatorTool = try context.tool(named: "my-code-generator") + extension \(typeName): XcodeBuildToolPlugin { + // Entry point for creating build commands for targets in Xcode projects. + func createBuildCommands(context: XcodePluginContext, target: XcodeTarget) throws -> [Command] { + // Find the code generator tool to run (replace this with the actual one). + let generatorTool = try context.tool(named: "my-code-generator") - // Construct a build command for each source file with a particular suffix. - return target.inputFiles.map(\\.url).compactMap { - createBuildCommand(for: $0, in: context.pluginWorkDirectoryURL, with: generatorTool.url) + // Construct a build command for each source file with a particular suffix. + return target.inputFiles.map(\\.url).compactMap { + createBuildCommand(for: $0, in: context.pluginWorkDirectoryURL, with: generatorTool.url) + } } } - } - #endif - - extension \(typeName) { - /// Shared function that returns a configured build command if the input files is one that should be processed. - func createBuildCommand(for inputPath: URL, in outputDirectoryPath: URL, with generatorToolPath: URL) -> Command? { - // Skip any file that doesn't have the extension we're looking for (replace this with the actual one). - guard inputPath.pathExtension == "my-input-suffix" else { return .none } - - // Return a command that will run during the build to generate the output file. - let inputName = inputPath.lastPathComponent - let outputName = inputPath.deletingPathExtension().lastPathComponent + ".swift" - let outputPath = outputDirectoryPath.appendingPathComponent(outputName) - return .buildCommand( - displayName: "Generating \\(outputName) from \\(inputName)", - executable: generatorToolPath, - arguments: ["\\(inputPath)", "-o", "\\(outputPath)"], - inputFiles: [inputPath], - outputFiles: [outputPath] - ) + #endif + + extension \(typeName) { + /// Shared function that returns a configured build command if the input files is one that should be processed. + func createBuildCommand(for inputPath: URL, in outputDirectoryPath: URL, with generatorToolPath: URL) -> Command? { + // Skip any file that doesn't have the extension we're looking for (replace this with the actual one). + guard inputPath.pathExtension == "my-input-suffix" else { return .none } + + // Return a command that will run during the build to generate the output file. + let inputName = inputPath.lastPathComponent + let outputName = inputPath.deletingPathExtension().lastPathComponent + ".swift" + let outputPath = outputDirectoryPath.appendingPathComponent(outputName) + return .buildCommand( + displayName: "Generating \\(outputName) from \\(inputName)", + executable: generatorToolPath, + arguments: ["\\(inputPath)", "-o", "\\(outputPath)"], + inputFiles: [inputPath], + outputFiles: [outputPath] + ) + } } - } - """ - } - else { + """ + } else { content += """ - struct \(typeName): CommandPlugin { - // Entry point for command plugins applied to Swift Packages. - func performCommand(context: PluginContext, arguments: [String]) async throws { - print("Hello, World!") + struct \(typeName): CommandPlugin { + // Entry point for command plugins applied to Swift Packages. + func performCommand(context: PluginContext, arguments: [String]) async throws { + print("Hello, World!") + } } - } - #if canImport(XcodeProjectPlugin) - import XcodeProjectPlugin + #if canImport(XcodeProjectPlugin) + import XcodeProjectPlugin - extension \(typeName): XcodeCommandPlugin { - // Entry point for command plugins applied to Xcode projects. - func performCommand(context: XcodePluginContext, arguments: [String]) throws { - print("Hello, World!") + extension \(typeName): XcodeCommandPlugin { + // Entry point for command plugins applied to Xcode projects. + func performCommand(context: XcodePluginContext, arguments: [String]) throws { + print("Hello, World!") + } } - } - #endif + #endif - """ + """ } try writePackageFile(sourceFile) { stream in @@ -642,37 +655,37 @@ public final class InitPackage { """ case .tool: content = """ - // The Swift Programming Language - // https://docs.swift.org/swift-book - // - // Swift Argument Parser - // https://swiftpackageindex.com/apple/swift-argument-parser/documentation - - import ArgumentParser - - @main - struct \(typeName): ParsableCommand { - mutating func run() throws { - print("Hello, world!") + // The Swift Programming Language + // https://docs.swift.org/swift-book + // + // Swift Argument Parser + // https://swiftpackageindex.com/apple/swift-argument-parser/documentation + + import ArgumentParser + + @main + struct \(typeName): ParsableCommand { + mutating func run() throws { + print("Hello, world!") + } } - } - """ + """ case .macro: content = """ - // The Swift Programming Language - // https://docs.swift.org/swift-book + // The Swift Programming Language + // https://docs.swift.org/swift-book - /// A macro that produces both a value and a string containing the - /// source code that generated the value. For example, - /// - /// #stringify(x + y) - /// - /// produces a tuple `(x + y, "x + y")`. - @freestanding(expression) - public macro stringify(_ value: T) -> (T, String) = #externalMacro(module: "\(moduleName)Macros", type: "StringifyMacro") + /// A macro that produces both a value and a string containing the + /// source code that generated the value. For example, + /// + /// #stringify(x + y) + /// + /// produces a tuple `(x + y, "x + y")`. + @freestanding(expression) + public macro stringify(_ value: T) -> (T, String) = #externalMacro(module: "\(moduleName)Macros", type: "StringifyMacro") - """ + """ case .empty, .buildToolPlugin, .commandPlugin: throw InternalError("invalid packageType \(packageType)") @@ -683,8 +696,8 @@ public final class InitPackage { } if packageType == .macro { - try writeMacroPluginSources(sources.appending("\(pkgname)Macros")) - try writeMacroClientSources(sources.appending("\(pkgname)Client")) + try writeMacroPluginSources(sources.appending("\(pkgname)Macros")) + try writeMacroClientSources(sources.appending("\(pkgname)Client")) } } diff --git a/Sources/Workspace/ManagedArtifact.swift b/Sources/Workspace/ManagedArtifact.swift index 3919250eae0..b5930c2605c 100644 --- a/Sources/Workspace/ManagedArtifact.swift +++ b/Sources/Workspace/ManagedArtifact.swift @@ -122,7 +122,7 @@ extension Workspace { private var artifactMap: [PackageIdentity: [String: ManagedArtifact]] internal var artifacts: AnyCollection { - AnyCollection(self.artifactMap.values.lazy.flatMap{ $0.values }) + AnyCollection(self.artifactMap.values.lazy.flatMap { $0.values }) } init() { @@ -131,7 +131,7 @@ extension Workspace { init(_ artifacts: [ManagedArtifact]) throws { let artifactsByPackagePath = Dictionary(grouping: artifacts, by: { $0.packageRef.identity }) - self.artifactMap = try artifactsByPackagePath.mapValues{ artifacts in + self.artifactMap = try artifactsByPackagePath.mapValues { artifacts in // rdar://86857825 do not use Dictionary(uniqueKeysWithValues:) as it can crash the process when input is incorrect such as in older versions of SwiftPM var map = [String: ManagedArtifact]() for artifact in artifacts { diff --git a/Sources/Workspace/ManagedDependency.swift b/Sources/Workspace/ManagedDependency.swift index dfbe53dd111..39386315ea1 100644 --- a/Sources/Workspace/ManagedDependency.swift +++ b/Sources/Workspace/ManagedDependency.swift @@ -86,7 +86,7 @@ extension Workspace { /// - subpath: The subpath inside the editable directory. /// - unmanagedPath: A custom absolute path instead of the subpath. public func edited(subpath: Basics.RelativePath, unmanagedPath: Basics.AbsolutePath?) throws -> ManagedDependency { - guard case .sourceControlCheckout = self.state else { + guard case .sourceControlCheckout = self.state else { throw InternalError("invalid dependency state: \(self.state)") } return ManagedDependency( @@ -179,7 +179,7 @@ extension Workspace { init() { self.dependencies = [:] } - + private init( _ dependencies: [PackageIdentity: ManagedDependency] ) { diff --git a/Sources/Workspace/ManagedPrebuilt.swift b/Sources/Workspace/ManagedPrebuilt.swift index de9a3d32fe2..5805019686f 100644 --- a/Sources/Workspace/ManagedPrebuilt.swift +++ b/Sources/Workspace/ManagedPrebuilt.swift @@ -60,7 +60,7 @@ extension Workspace { private var prebuiltMap: [PackageIdentity: [String: ManagedPrebuilt]] internal var prebuilts: AnyCollection { - AnyCollection(self.prebuiltMap.values.lazy.flatMap{ $0.values }) + AnyCollection(self.prebuiltMap.values.lazy.flatMap { $0.values }) } init() { @@ -69,11 +69,14 @@ extension Workspace { init(_ prebuilts: [ManagedPrebuilt]) throws { let prebuiltsByPackagePath = Dictionary(grouping: prebuilts, by: { $0.identity }) - self.prebuiltMap = try prebuiltsByPackagePath.mapValues{ prebuilt in - try Dictionary(prebuilt.map { ($0.libraryName, $0) }, uniquingKeysWith: { _, _ in - // should be unique - throw StringError("prebuilt already exists in managed prebuilts") - }) + self.prebuiltMap = try prebuiltsByPackagePath.mapValues { prebuilt in + try Dictionary( + prebuilt.map { ($0.libraryName, $0) }, + uniquingKeysWith: { _, _ in + // should be unique + throw StringError("prebuilt already exists in managed prebuilts") + } + ) } } diff --git a/Sources/Workspace/ManifestSigning/Base64URL.swift b/Sources/Workspace/ManifestSigning/Base64URL.swift index bae48bb4c62..9b563854761 100644 --- a/Sources/Workspace/ManifestSigning/Base64URL.swift +++ b/Sources/Workspace/ManifestSigning/Base64URL.swift @@ -46,7 +46,7 @@ extension Data { /// /// https://tools.ietf.org/html/rfc4648#page-7 mutating func base64URLUnescape() { - for i in 0 ..< self.count { + for i in 0.. PolicyEvaluationResult { - let isCodeSigning = ( - try? chain.leaf.extensions.extendedKeyUsage?.contains(ExtendedKeyUsage.Usage.codeSigning) - ) ?? false + let isCodeSigning = (try? chain.leaf.extensions.extendedKeyUsage?.contains(ExtendedKeyUsage.Usage.codeSigning)) ?? false guard isCodeSigning else { return .failsToMeetPolicy(reason: "Certificate \(chain.leaf) does not have code signing extended key usage") } @@ -480,7 +478,7 @@ struct _ADPCertificatePolicy: VerifierPolicy { /// Include custom marker extensions (which can be critical) so they would not /// be considered unhandled and cause certificate chain validation to fail. let verifyingCriticalExtensions: [ASN1ObjectIdentifier] = - ASN1ObjectIdentifier.NameAttributes.adpAppleDevelopmentMarkers // included for testing + ASN1ObjectIdentifier.NameAttributes.adpAppleDevelopmentMarkers // included for testing func chainMeetsPolicyRequirements(chain: UnverifiedCertificateChain) async -> PolicyEvaluationResult { // Not policing anything here. This policy is mainly for @@ -511,8 +509,9 @@ struct _ADPSwiftPackageCertificatePolicy: VerifierPolicy { // Package collection can be signed with "Swift Package Collection" // or "Swift Package" certificate - guard chain.leaf.hasExtension(oid: ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageCollectionMarker) - || chain.leaf.hasExtension(oid: ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageMarker) + guard + chain.leaf.hasExtension(oid: ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageCollectionMarker) + || chain.leaf.hasExtension(oid: ASN1ObjectIdentifier.NameAttributes.adpSwiftPackageMarker) else { return .failsToMeetPolicy(reason: "Leaf certificate missing marker OID") } diff --git a/Sources/Workspace/ManifestSigning/ManifestSigning.swift b/Sources/Workspace/ManifestSigning/ManifestSigning.swift index 4f3bb2808c7..117875eb8ff 100644 --- a/Sources/Workspace/ManifestSigning/ManifestSigning.swift +++ b/Sources/Workspace/ManifestSigning/ManifestSigning.swift @@ -10,20 +10,19 @@ // //===----------------------------------------------------------------------===// - import Basics import Dispatch import Foundation import SwiftASN1 #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import _CryptoExtras -@_implementationOnly import Crypto -@_implementationOnly import X509 + @_implementationOnly import _CryptoExtras + @_implementationOnly import Crypto + @_implementationOnly import X509 #else -import _CryptoExtras -import Crypto -import X509 + import _CryptoExtras + import Crypto + import X509 #endif public struct ManifestSignature: Equatable, Codable { @@ -66,10 +65,12 @@ public struct ManifestSignature: Equatable, Codable { public let organization: String? /// Creates a `Name` - public init(userID: String?, - commonName: String?, - organizationalUnit: String?, - organization: String?) { + public init( + userID: String?, + commonName: String?, + organizationalUnit: String?, + organization: String? + ) { self.userID = userID self.commonName = commonName self.organizationalUnit = organizationalUnit @@ -162,21 +163,23 @@ public actor ManifestSigning: ManifestSigner, ManifestSignatureValidator { observabilityScope: ObservabilityScope ) { self.trustedRootCertsDir = trustedRootCertsDir - self.additionalTrustedRootCerts = additionalTrustedRootCerts.map { $0.compactMap { - guard let data = Data(base64Encoded: $0) else { - observabilityScope.emit(error: "The certificate \($0) is not in valid base64 encoding") - return nil - } - do { - return try Certificate(derEncoded: Array(data)) - } catch { - observabilityScope.emit( - error: "The certificate \($0) is not in valid DER format", - underlyingError: error - ) - return nil + self.additionalTrustedRootCerts = additionalTrustedRootCerts.map { + $0.compactMap { + guard let data = Data(base64Encoded: $0) else { + observabilityScope.emit(error: "The certificate \($0) is not in valid base64 encoding") + return nil + } + do { + return try Certificate(derEncoded: Array(data)) + } catch { + observabilityScope.emit( + error: "The certificate \($0) is not in valid DER format", + underlyingError: error + ) + return nil + } } - } } + } self.certPolicies = [:] self.encoder = JSONEncoder.makeWithDefaults() @@ -291,7 +294,7 @@ public actor ManifestSigning: ManifestSigner, ManifestSignatureValidator { throw ManifestSigningError.invalidSignature } - let certificate = certChain.first! // !-safe because certChain cannot be empty at this point + let certificate = certChain.first! // !-safe because certChain cannot be empty at this point return ManifestSignature( signature: signature, certificate: ManifestSignature.Certificate( diff --git a/Sources/Workspace/ManifestSigning/Signature.swift b/Sources/Workspace/ManifestSigning/Signature.swift index 76e27d45d10..a019e29e43f 100644 --- a/Sources/Workspace/ManifestSigning/Signature.swift +++ b/Sources/Workspace/ManifestSigning/Signature.swift @@ -26,13 +26,13 @@ import Foundation #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import _CryptoExtras -@_implementationOnly import Crypto -@_implementationOnly import X509 + @_implementationOnly import _CryptoExtras + @_implementationOnly import Crypto + @_implementationOnly import X509 #else -import _CryptoExtras -import Crypto -import X509 + import _CryptoExtras + import Crypto + import X509 #endif // The logic in this source file loosely follows https://www.rfc-editor.org/rfc/rfc7515.html @@ -46,8 +46,8 @@ struct Signature { extension Signature { enum Algorithm: String, Codable { - case RS256 // RSASSA-PKCS1-v1_5 using SHA-256 - case ES256 // ECDSA using P-256 and SHA-256 + case RS256 // RSASSA-PKCS1-v1_5 using SHA-256 + case ES256 // ECDSA using P-256 and SHA-256 } struct Header: Equatable, Codable { @@ -91,7 +91,8 @@ extension Signature { let encodedSignature = signatureData.base64URLEncodedBytes() // Result: header.payload.signature - let bytes = encodedHeader + let bytes = + encodedHeader + .period + encodedPayload + .period @@ -128,7 +129,7 @@ extension Signature { let encodedSignature = parts[2] guard let headerBytes = encodedHeader.base64URLDecodedBytes(), - let header = try? jsonDecoder.decode(Header.self, from: headerBytes) + let header = try? jsonDecoder.decode(Header.self, from: headerBytes) else { throw SignatureError.malformedSignature } @@ -143,13 +144,13 @@ extension Signature { let certChain = try await certChainValidate(certChainData) guard let payloadBytes = encodedPayload.base64URLDecodedBytes(), - let signatureBytes = encodedSignature.base64URLDecodedBytes() + let signatureBytes = encodedSignature.base64URLDecodedBytes() else { throw SignatureError.malformedSignature } // Extract public key from the certificate - let certificate = certChain.first! // !-safe because certChain is not empty at this point + let certificate = certChain.first! // !-safe because certChain is not empty at this point // Verify the key was used to generate the signature let message = Data(encodedHeader) + .period + Data(encodedPayload) let digest = SHA256.hash(data: message) @@ -167,11 +168,13 @@ extension Signature { guard let publicKey = _RSA.Signing.PublicKey(certificate.publicKey) else { throw SignatureError.invalidPublicKey } - guard publicKey.isValidSignature( - .init(rawRepresentation: signatureBytes), - for: digest, - padding: .insecurePKCS1v1_5 - ) else { + guard + publicKey.isValidSignature( + .init(rawRepresentation: signatureBytes), + for: digest, + padding: .insecurePKCS1v1_5 + ) + else { throw SignatureError.invalidSignature } } diff --git a/Sources/Workspace/ManifestSigning/X509Extensions.swift b/Sources/Workspace/ManifestSigning/X509Extensions.swift index bef5d7ca1ce..beec3bb85b8 100644 --- a/Sources/Workspace/ManifestSigning/X509Extensions.swift +++ b/Sources/Workspace/ManifestSigning/X509Extensions.swift @@ -11,11 +11,11 @@ //===----------------------------------------------------------------------===// #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import SwiftASN1 -@_implementationOnly import X509 + @_implementationOnly import SwiftASN1 + @_implementationOnly import X509 #else -import SwiftASN1 -import X509 + import SwiftASN1 + import X509 #endif extension Certificate { diff --git a/Sources/Workspace/ManifestSigning/embedded_resources.swift b/Sources/Workspace/ManifestSigning/embedded_resources.swift index a1dbeb69b2f..04e426ab004 100644 --- a/Sources/Workspace/ManifestSigning/embedded_resources.swift +++ b/Sources/Workspace/ManifestSigning/embedded_resources.swift @@ -1,13 +1,13 @@ struct PackageResources { -static let AppleWWDRCAG2_cer: [UInt8] = [48,130,2,247,48,130,2,124,160,3,2,1,2,2,8,111,239,216,245,233,163,167,238,48,10,6,8,42,134,72,206,61,4,3,2,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,51,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,30,23,13,49,52,48,53,48,54,50,51,52,51,50,52,90,23,13,50,57,48,53,48,54,50,51,52,51,50,52,90,48,129,128,49,52,48,50,6,3,85,4,3,12,43,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,65,32,45,32,71,50,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,89,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,3,66,0,4,221,240,183,6,75,207,221,115,4,19,196,67,137,3,147,128,251,94,246,116,173,66,97,82,88,2,38,83,25,200,99,34,7,9,82,97,202,196,217,87,239,109,38,104,139,116,145,140,196,249,128,104,40,252,9,104,240,16,218,233,208,46,201,26,163,129,247,48,129,244,48,70,6,8,43,6,1,5,5,7,1,1,4,58,48,56,48,54,6,8,43,6,1,5,5,7,48,1,134,42,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,52,45,97,112,112,108,101,114,111,111,116,99,97,103,51,48,29,6,3,85,29,14,4,22,4,20,132,182,132,204,58,134,98,114,22,89,148,232,26,163,189,72,223,58,223,11,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,31,6,3,85,29,35,4,24,48,22,128,20,187,176,222,161,88,51,136,154,164,138,153,222,190,189,235,175,218,203,36,171,48,55,6,3,85,29,31,4,48,48,46,48,44,160,42,160,40,134,38,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,97,112,112,108,101,114,111,111,116,99,97,103,51,46,99,114,108,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,15,4,2,5,0,48,10,6,8,42,134,72,206,61,4,3,2,3,105,0,48,102,2,49,0,217,177,199,49,198,35,246,79,77,208,217,71,197,125,24,105,17,135,113,39,211,104,173,224,155,101,154,190,108,223,63,70,166,144,9,190,110,161,59,44,176,81,137,65,60,135,210,191,2,49,0,252,100,82,137,75,60,93,191,107,28,194,137,152,47,114,174,181,155,170,26,11,35,84,119,84,232,21,67,162,197,18,218,151,80,115,124,94,208,110,178,92,98,80,215,81,241,58,90] -static let AppleWWDRCAG3_cer: [UInt8] = [48,130,4,81,48,130,3,57,160,3,2,1,2,2,16,124,175,105,10,37,183,57,254,123,155,68,122,193,120,197,238,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,48,48,50,49,57,49,56,49,51,52,55,90,23,13,51,48,48,50,50,48,48,48,48,48,48,48,90,48,117,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,11,48,9,6,3,85,4,11,12,2,71,51,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,216,245,137,252,168,89,11,135,199,76,145,46,45,86,144,211,120,29,164,48,233,165,72,239,11,67,191,45,132,251,36,93,69,27,229,235,89,54,18,92,84,100,158,108,98,45,180,198,151,202,204,60,246,214,6,145,252,229,2,166,28,106,180,121,213,103,203,172,233,63,7,17,225,132,188,71,29,102,142,57,162,232,180,73,237,58,210,225,16,96,122,142,147,140,202,192,218,12,192,131,208,227,249,145,214,167,140,200,193,115,226,174,70,209,98,157,146,168,144,96,55,125,104,150,205,141,224,252,155,250,120,187,227,123,175,45,23,221,91,254,128,89,35,117,23,184,18,193,237,27,229,52,206,254,34,181,158,73,176,229,85,191,143,132,162,60,168,186,197,134,149,22,228,0,201,159,3,208,204,179,58,22,123,214,5,92,157,235,71,174,13,181,45,140,14,105,77,64,208,75,76,59,4,158,141,33,177,172,46,67,84,48,206,193,138,134,148,152,75,223,106,13,63,254,251,28,174,151,23,194,120,10,48,224,95,31,84,59,73,183,37,0,26,55,130,210,86,151,165,82,73,124,96,56,155,239,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,9,254,192,21,144,249,175,100,10,146,18,185,38,40,99,12,151,236,167,178,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,3,130,1,1,0,173,101,19,232,246,224,129,119,68,2,71,66,190,95,165,57,32,234,98,169,253,197,144,201,115,19,213,158,155,208,170,15,141,141,203,237,1,207,108,40,64,91,199,85,36,65,248,252,207,193,181,35,233,220,236,241,111,202,128,29,119,194,196,97,73,37,103,175,15,202,57,37,173,211,227,122,204,51,40,13,14,46,161,87,64,115,250,230,92,174,6,81,41,237,227,133,12,79,97,220,50,22,139,119,208,68,202,93,114,3,49,70,156,174,155,64,26,250,244,224,211,62,250,47,140,102,159,151,196,84,89,239,210,72,244,7,153,73,96,89,25,199,221,148,209,192,193,108,127,120,33,239,12,235,59,108,153,130,75,82,96,56,181,57,130,109,236,82,49,83,190,15,145,76,73,73,116,143,166,81,203,132,71,78,29,117,39,110,189,249,210,92,243,127,194,108,11,9,54,226,100,228,194,55,3,20,25,213,234,106,148,170,169,219,254,246,154,8,103,139,239,43,184,170,23,73,131,175,207,203,188,233,207,234,149,113,176,180,69,162,204,229,135,170,10,195,65,58,121,92,218,80,52,157,149,59] -static let AppleWWDRCAG5_cer: [UInt8] = [48,130,4,85,48,130,3,61,160,3,2,1,2,2,20,59,126,128,10,238,211,2,161,230,236,219,151,217,202,172,40,156,241,105,148,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,48,49,50,49,54,49,57,51,56,53,54,90,23,13,51,48,49,50,49,48,48,48,48,48,48,48,90,48,117,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,11,48,9,6,3,85,4,11,12,2,71,53,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,159,93,218,31,251,250,188,208,75,34,60,199,214,38,250,23,247,244,159,30,62,100,17,102,154,239,94,190,171,52,189,170,44,33,110,214,30,148,33,133,44,116,193,14,16,97,170,60,99,74,126,74,227,200,117,214,207,194,156,8,72,123,106,185,41,177,201,102,253,200,138,22,209,178,4,60,130,186,128,108,226,255,10,114,235,172,254,59,111,72,190,158,139,17,77,149,125,178,123,144,47,2,28,78,252,73,190,215,111,181,79,190,120,198,218,222,178,205,201,217,102,17,59,90,233,9,69,115,137,80,212,78,226,104,5,126,218,117,156,75,1,174,218,227,207,109,116,77,222,83,208,213,26,56,130,58,208,157,227,93,41,123,177,129,234,41,39,11,251,96,124,134,18,251,240,98,79,6,231,76,209,31,217,109,158,237,115,218,120,33,13,157,112,217,70,87,144,95,103,132,193,115,119,10,168,98,98,182,174,112,134,187,117,35,137,173,121,246,230,164,212,253,131,38,50,10,59,36,146,91,32,161,156,209,47,128,24,155,221,60,11,231,181,253,236,128,87,15,23,158,63,43,135,39,187,247,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,25,139,151,141,74,91,97,120,87,244,165,92,53,18,138,57,8,227,176,117,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,3,130,1,1,0,90,196,53,162,217,230,10,158,82,162,0,130,34,119,205,114,47,144,249,34,175,20,37,204,170,10,66,96,146,194,189,117,29,235,76,202,21,229,126,107,64,16,94,251,91,69,116,13,240,122,125,136,145,206,222,99,139,66,137,210,24,223,65,179,88,158,6,8,135,72,221,64,175,35,213,237,235,44,96,229,235,164,127,28,233,156,131,214,148,95,76,98,57,138,78,174,19,141,125,67,184,220,94,172,190,24,64,242,230,15,44,93,19,147,241,123,101,168,194,104,72,222,255,180,150,155,12,251,50,54,158,158,13,149,95,56,10,139,150,210,18,108,183,139,11,142,215,62,236,111,1,170,206,77,69,96,219,132,113,102,98,229,25,101,48,205,138,255,69,83,251,110,251,136,119,67,195,72,99,249,247,81,179,114,94,121,226,86,207,188,187,132,185,56,90,120,174,17,72,82,187,13,53,139,148,222,204,116,154,104,245,73,96,148,172,242,168,179,21,134,144,208,204,48,67,134,211,229,112,2,81,180,129,192,168,151,212,234,234,176,140,9,64,239,56,147,178,205,34,3,235,103,67,101,200,69] -static let AppleRootCA_G2_cer: [UInt8] = [48,130,5,146,48,130,3,122,160,3,2,1,2,2,8,1,224,229,181,131,103,163,224,48,13,6,9,42,134,72,134,247,13,1,1,12,5,0,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,50,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,30,23,13,49,52,48,52,51,48,49,56,49,48,48,57,90,23,13,51,57,48,52,51,48,49,56,49,48,48,57,90,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,50,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,130,2,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,2,15,0,48,130,2,10,2,130,2,1,0,216,17,18,72,72,218,41,138,73,197,28,199,236,110,51,109,254,77,251,224,28,222,172,94,226,54,167,36,249,127,80,107,76,206,185,48,84,39,229,179,214,237,37,230,48,182,5,55,94,20,34,17,197,232,170,27,210,251,178,210,9,149,56,164,239,42,73,140,93,62,113,102,3,56,251,22,245,133,136,228,90,146,12,4,50,242,200,64,251,82,95,159,246,192,241,227,186,69,160,80,213,18,139,242,221,222,145,134,35,240,245,182,114,46,1,218,11,246,46,57,8,95,25,161,99,65,11,28,167,148,193,134,196,83,47,118,246,10,215,12,209,131,63,26,83,25,243,87,213,39,127,252,19,184,248,146,141,252,211,40,67,60,181,104,0,37,93,39,98,211,221,85,221,68,32,144,131,53,147,197,191,184,25,251,107,227,220,8,66,230,175,109,250,158,64,202,78,133,133,120,73,177,215,195,193,48,57,50,171,126,95,170,211,139,111,159,45,26,33,104,112,103,179,163,241,152,65,109,145,124,248,215,219,168,231,95,33,26,140,51,191,49,116,183,184,209,244,224,34,244,191,114,52,223,247,129,77,113,125,81,161,226,179,240,211,40,22,115,111,205,204,173,55,125,78,235,173,64,225,63,129,253,247,61,10,62,162,241,189,49,150,41,89,220,194,25,128,140,91,116,198,44,211,16,83,38,29,20,79,196,212,129,102,60,135,103,51,39,20,8,233,180,119,132,52,82,143,137,248,104,152,23,191,195,187,170,19,147,31,93,84,47,168,199,124,251,13,20,190,21,61,36,52,242,154,220,117,65,102,34,180,1,214,11,175,144,158,12,234,98,248,155,89,60,8,226,150,52,228,99,222,188,55,212,235,12,136,3,67,11,80,175,160,52,221,80,77,21,251,90,36,216,12,250,12,99,158,31,3,177,225,238,225,170,67,244,102,101,40,55,2,49,239,1,199,30,209,204,159,109,202,84,58,64,219,206,207,79,70,139,74,101,154,106,198,104,108,215,204,153,27,71,176,114,195,119,143,196,247,97,156,116,31,206,253,107,161,194,156,148,130,171,148,162,231,189,27,186,185,112,57,149,23,197,41,243,57,88,52,245,196,164,198,123,96,185,102,67,80,63,110,97,252,14,249,134,170,96,12,67,75,149,2,3,1,0,1,163,66,48,64,48,29,6,3,85,29,14,4,22,4,20,196,153,19,108,24,3,194,123,192,163,160,13,127,114,128,122,28,119,38,141,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,13,6,9,42,134,72,134,247,13,1,1,12,5,0,3,130,2,1,0,81,166,243,226,244,184,61,147,191,45,206,15,187,91,225,85,20,78,78,209,229,206,121,93,129,127,254,182,240,135,51,248,239,148,229,126,220,106,121,167,28,190,240,148,183,166,209,48,156,200,13,10,117,158,125,146,149,126,24,157,126,194,113,105,124,20,234,207,131,14,228,20,66,158,116,14,16,205,171,26,186,17,97,129,120,216,241,181,69,64,120,171,168,192,206,251,125,99,55,104,246,231,251,175,198,195,75,236,31,54,38,19,84,134,148,114,178,234,2,237,139,109,228,12,166,144,192,87,117,207,140,66,125,92,230,49,125,243,201,178,146,105,70,14,136,248,227,45,66,178,56,168,166,25,141,241,159,205,238,106,101,188,26,176,37,189,167,41,253,244,62,162,117,73,191,158,219,201,247,167,30,99,153,225,92,70,255,146,5,140,250,30,32,249,134,148,86,37,229,180,87,56,157,235,136,100,20,33,73,33,57,191,98,102,169,177,162,202,111,63,33,96,197,137,212,69,54,200,152,124,189,246,254,153,73,128,59,44,210,166,167,136,3,4,49,25,183,182,58,97,69,250,201,242,35,200,99,115,191,86,137,49,176,217,124,98,167,123,21,168,136,138,171,56,64,194,204,18,255,21,227,240,55,223,55,114,203,204,152,230,191,162,188,250,38,138,113,86,215,231,36,27,72,68,62,158,252,159,201,204,26,236,67,60,1,188,52,120,200,105,245,198,230,86,236,6,9,54,144,235,20,74,27,94,201,136,35,218,3,48,145,11,184,54,62,249,231,181,40,111,190,63,236,60,143,101,29,229,192,30,135,164,170,186,152,253,146,227,108,38,119,221,6,180,100,6,135,244,78,214,186,74,170,22,168,244,5,103,102,150,186,226,85,121,195,44,93,73,143,128,73,43,138,18,199,118,128,81,223,186,189,101,93,62,55,71,99,49,233,229,244,197,63,75,173,4,138,122,113,44,175,9,67,55,15,168,227,50,79,244,69,182,109,151,54,236,132,245,10,1,234,23,187,133,141,66,147,112,195,80,229,20,139,191,63,195,65,15,221,34,4,35,8,138,186,109,113,68,171,115,9,58,201,249,82,128,9,223,186,233,230,22,202,46,46,76,178,211,220,229,4,84,178,212,52,128,50,181,188,15,23,225] -static let AppleComputerRootCertificate_cer: [UInt8] = [48,130,5,186,48,130,4,162,160,3,2,1,2,2,1,1,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,129,134,49,11,48,9,6,3,85,4,6,19,2,85,83,49,29,48,27,6,3,85,4,10,19,20,65,112,112,108,101,32,67,111,109,112,117,116,101,114,44,32,73,110,99,46,49,45,48,43,6,3,85,4,11,19,36,65,112,112,108,101,32,67,111,109,112,117,116,101,114,32,67,101,114,116,105,102,105,99,97,116,101,32,65,117,116,104,111,114,105,116,121,49,41,48,39,6,3,85,4,3,19,32,65,112,112,108,101,32,82,111,111,116,32,67,101,114,116,105,102,105,99,97,116,101,32,65,117,116,104,111,114,105,116,121,48,30,23,13,48,53,48,50,49,48,48,48,49,56,49,52,90,23,13,50,53,48,50,49,48,48,48,49,56,49,52,90,48,129,134,49,11,48,9,6,3,85,4,6,19,2,85,83,49,29,48,27,6,3,85,4,10,19,20,65,112,112,108,101,32,67,111,109,112,117,116,101,114,44,32,73,110,99,46,49,45,48,43,6,3,85,4,11,19,36,65,112,112,108,101,32,67,111,109,112,117,116,101,114,32,67,101,114,116,105,102,105,99,97,116,101,32,65,117,116,104,111,114,105,116,121,49,41,48,39,6,3,85,4,3,19,32,65,112,112,108,101,32,82,111,111,116,32,67,101,114,116,105,102,105,99,97,116,101,32,65,117,116,104,111,114,105,116,121,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,228,145,169,9,31,145,219,30,71,80,235,5,237,94,121,132,45,235,54,162,87,76,85,236,139,25,137,222,249,75,108,245,7,171,34,48,2,232,24,62,248,80,9,211,127,65,168,152,249,209,202,102,156,36,107,17,208,163,187,228,27,42,195,31,149,158,122,12,164,71,139,91,212,22,55,51,203,196,15,77,206,20,105,209,201,25,114,245,93,14,213,127,95,155,242,37,3,186,85,143,77,93,13,241,100,53,35,21,75,21,89,29,179,148,247,246,156,158,207,80,186,193,88,80,103,143,8,180,32,247,203,172,44,32,111,112,182,63,1,48,140,183,67,207,15,157,61,243,43,73,40,26,200,254,206,181,185,14,217,94,28,214,203,61,181,58,173,244,15,14,0,146,11,177,33,22,46,116,213,60,13,219,98,22,171,163,113,146,71,83,85,193,175,47,65,179,248,251,227,112,205,230,163,76,69,126,31,76,107,80,150,65,137,196,116,98,11,16,131,65,135,51,138,129,177,48,88,236,90,4,50,140,104,179,143,29,222,101,115,255,103,94,101,188,73,216,118,159,51,20,101,161,119,148,201,45,2,3,1,0,1,163,130,2,47,48,130,2,43,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,29,6,3,85,29,14,4,22,4,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,130,1,41,6,3,85,29,32,4,130,1,32,48,130,1,28,48,130,1,24,6,9,42,134,72,134,247,99,100,5,1,48,130,1,9,48,65,6,8,43,6,1,5,5,7,2,1,22,53,104,116,116,112,115,58,47,47,119,119,119,46,97,112,112,108,101,46,99,111,109,47,99,101,114,116,105,102,105,99,97,116,101,97,117,116,104,111,114,105,116,121,47,116,101,114,109,115,46,104,116,109,108,48,129,195,6,8,43,6,1,5,5,7,2,2,48,129,182,26,129,179,82,101,108,105,97,110,99,101,32,111,110,32,116,104,105,115,32,99,101,114,116,105,102,105,99,97,116,101,32,98,121,32,97,110,121,32,112,97,114,116,121,32,97,115,115,117,109,101,115,32,97,99,99,101,112,116,97,110,99,101,32,111,102,32,116,104,101,32,116,104,101,110,32,97,112,112,108,105,99,97,98,108,101,32,115,116,97,110,100,97,114,100,32,116,101,114,109,115,32,97,110,100,32,99,111,110,100,105,116,105,111,110,115,32,111,102,32,117,115,101,44,32,99,101,114,116,105,102,105,99,97,116,101,32,112,111,108,105,99,121,32,97,110,100,32,99,101,114,116,105,102,105,99,97,116,105,111,110,32,112,114,97,99,116,105,99,101,32,115,116,97,116,101,109,101,110,116,115,46,48,68,6,3,85,29,31,4,61,48,59,48,57,160,55,160,53,134,51,104,116,116,112,115,58,47,47,119,119,119,46,97,112,112,108,101,46,99,111,109,47,99,101,114,116,105,102,105,99,97,116,101,97,117,116,104,111,114,105,116,121,47,114,111,111,116,46,99,114,108,48,85,6,8,43,6,1,5,5,7,1,1,4,73,48,71,48,69,6,8,43,6,1,5,5,7,48,2,134,57,104,116,116,112,115,58,47,47,119,119,119,46,97,112,112,108,101,46,99,111,109,47,99,101,114,116,105,102,105,99,97,116,101,97,117,116,104,111,114,105,116,121,47,99,97,115,105,103,110,101,114,115,46,104,116,109,108,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,130,1,1,0,157,218,45,40,88,47,125,118,4,185,4,211,62,206,183,102,99,78,143,47,212,254,75,173,114,189,163,57,198,82,77,5,152,82,245,137,81,1,36,121,190,26,50,247,229,68,139,75,68,7,57,130,214,90,202,180,32,94,217,174,21,93,29,140,29,50,191,56,49,98,72,93,199,225,144,177,248,36,64,248,95,88,155,81,93,87,157,193,229,255,60,204,114,33,110,196,233,233,161,119,215,44,23,38,195,63,235,154,232,11,3,186,233,179,74,114,235,51,9,91,173,230,98,49,106,232,175,47,213,175,30,87,118,143,127,55,45,46,2,92,221,99,201,242,113,184,38,64,223,21,141,117,68,63,121,189,230,29,153,225,67,44,62,173,111,190,185,164,254,14,53,25,81,99,177,195,222,181,146,62,81,120,1,115,138,164,35,202,164,136,241,30,92,31,65,22,45,126,149,10,170,233,137,65,152,27,26,221,203,32,191,71,94,12,38,197,85,53,77,198,48,139,153,103,20,199,9,31,186,71,199,218,1,9,135,36,66,149,189,19,96,25,10,239,234,127,14,110,205,193,68,67,58,74,213,227] -static let AppleWWDRCAG7_cer: [UInt8] = [48,130,4,85,48,130,3,61,160,3,2,1,2,2,20,52,24,88,255,1,254,6,63,142,241,159,31,233,60,1,180,193,70,255,201,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,50,49,49,49,55,50,48,52,48,53,51,90,23,13,50,51,49,49,49,55,50,48,52,48,53,50,90,48,117,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,11,12,2,71,55,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,172,174,209,211,182,138,177,27,40,149,173,222,81,81,76,63,51,225,78,92,175,179,252,2,210,101,79,42,212,116,104,140,117,23,101,207,40,228,72,9,152,113,82,50,44,22,78,120,142,146,86,100,169,221,139,205,226,212,199,59,162,18,69,55,2,25,98,100,47,127,97,198,211,89,34,191,171,249,20,163,237,182,158,153,186,47,241,177,220,48,66,79,182,182,178,198,116,170,98,86,187,237,68,54,15,209,229,32,116,147,87,58,93,158,220,1,252,120,111,105,22,53,195,110,1,194,158,114,212,113,54,177,118,9,122,190,13,42,151,241,176,94,11,27,18,173,43,171,7,223,99,45,245,136,233,50,18,162,85,88,67,118,60,61,23,128,31,41,219,177,169,159,171,150,5,157,21,220,221,219,78,15,231,19,124,90,43,46,2,65,246,238,122,106,182,115,96,247,151,25,20,139,149,51,56,147,218,0,37,54,174,85,90,124,159,249,244,98,4,7,116,233,29,167,149,87,35,172,43,36,218,100,79,40,114,233,150,176,8,60,136,27,20,99,67,215,137,174,152,193,242,45,142,227,81,37,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,93,66,16,108,27,187,199,82,151,78,68,189,19,39,185,58,18,119,131,43,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,130,1,1,0,82,163,8,41,19,101,183,181,31,230,52,3,237,246,24,119,188,61,202,39,181,112,236,236,108,51,75,246,153,37,148,7,158,33,51,3,106,245,125,10,46,43,223,8,169,130,222,74,127,225,231,11,75,5,184,39,152,73,221,193,12,134,215,129,100,174,130,156,196,69,241,234,143,28,34,48,227,162,37,97,68,137,254,133,122,86,240,114,146,124,12,68,84,36,183,181,164,159,38,240,50,249,87,157,106,121,108,64,237,15,52,6,6,66,255,216,14,49,101,109,230,46,1,217,6,191,197,202,13,174,71,212,5,23,136,60,233,156,228,25,100,109,138,148,173,17,220,1,246,229,120,175,173,232,112,215,13,93,129,62,70,42,44,174,36,161,199,210,224,125,191,29,245,54,107,197,222,169,10,154,128,177,17,94,178,100,126,179,193,87,204,194,108,89,153,183,244,176,221,49,218,72,214,106,129,238,178,139,80,53,22,230,231,92,113,98,110,176,242,81,226,168,109,248,42,203,104,115,198,166,196,26,67,73,1,62,169,169,0,138,134,108,131,136,210,92,112,87,122,218,248,118,204,25,213,176] -static let AppleIncRootCertificate_cer: [UInt8] = [48,130,4,187,48,130,3,163,160,3,2,1,2,2,1,2,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,48,54,48,52,50,53,50,49,52,48,51,54,90,23,13,51,53,48,50,48,57,50,49,52,48,51,54,90,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,228,145,169,9,31,145,219,30,71,80,235,5,237,94,121,132,45,235,54,162,87,76,85,236,139,25,137,222,249,75,108,245,7,171,34,48,2,232,24,62,248,80,9,211,127,65,168,152,249,209,202,102,156,36,107,17,208,163,187,228,27,42,195,31,149,158,122,12,164,71,139,91,212,22,55,51,203,196,15,77,206,20,105,209,201,25,114,245,93,14,213,127,95,155,242,37,3,186,85,143,77,93,13,241,100,53,35,21,75,21,89,29,179,148,247,246,156,158,207,80,186,193,88,80,103,143,8,180,32,247,203,172,44,32,111,112,182,63,1,48,140,183,67,207,15,157,61,243,43,73,40,26,200,254,206,181,185,14,217,94,28,214,203,61,181,58,173,244,15,14,0,146,11,177,33,22,46,116,213,60,13,219,98,22,171,163,113,146,71,83,85,193,175,47,65,179,248,251,227,112,205,230,163,76,69,126,31,76,107,80,150,65,137,196,116,98,11,16,131,65,135,51,138,129,177,48,88,236,90,4,50,140,104,179,143,29,222,101,115,255,103,94,101,188,73,216,118,159,51,20,101,161,119,148,201,45,2,3,1,0,1,163,130,1,122,48,130,1,118,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,29,6,3,85,29,14,4,22,4,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,130,1,17,6,3,85,29,32,4,130,1,8,48,130,1,4,48,130,1,0,6,9,42,134,72,134,247,99,100,5,1,48,129,242,48,42,6,8,43,6,1,5,5,7,2,1,22,30,104,116,116,112,115,58,47,47,119,119,119,46,97,112,112,108,101,46,99,111,109,47,97,112,112,108,101,99,97,47,48,129,195,6,8,43,6,1,5,5,7,2,2,48,129,182,26,129,179,82,101,108,105,97,110,99,101,32,111,110,32,116,104,105,115,32,99,101,114,116,105,102,105,99,97,116,101,32,98,121,32,97,110,121,32,112,97,114,116,121,32,97,115,115,117,109,101,115,32,97,99,99,101,112,116,97,110,99,101,32,111,102,32,116,104,101,32,116,104,101,110,32,97,112,112,108,105,99,97,98,108,101,32,115,116,97,110,100,97,114,100,32,116,101,114,109,115,32,97,110,100,32,99,111,110,100,105,116,105,111,110,115,32,111,102,32,117,115,101,44,32,99,101,114,116,105,102,105,99,97,116,101,32,112,111,108,105,99,121,32,97,110,100,32,99,101,114,116,105,102,105,99,97,116,105,111,110,32,112,114,97,99,116,105,99,101,32,115,116,97,116,101,109,101,110,116,115,46,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,130,1,1,0,92,54,153,76,45,120,183,237,140,155,220,243,119,155,242,118,210,119,48,79,193,31,133,131,133,27,153,61,71,55,242,169,155,64,142,44,212,177,144,18,216,190,244,115,155,238,210,100,15,203,121,79,52,216,162,62,249,120,255,107,200,7,236,125,57,131,139,83,32,211,56,196,177,191,154,79,10,107,255,43,252,89,167,5,9,124,23,64,86,17,30,116,211,183,139,35,59,71,163,213,111,36,226,235,209,183,112,223,15,69,225,39,202,241,109,120,237,231,181,23,23,168,220,126,34,53,202,37,213,217,15,214,107,212,162,36,35,17,247,161,172,143,115,129,96,198,27,91,9,47,146,178,248,68,72,240,96,56,158,21,245,61,38,103,32,138,51,106,247,13,130,207,222,235,163,47,249,83,106,91,100,192,99,51,119,247,58,7,44,86,235,218,15,33,14,218,186,115,25,79,181,217,54,127,193,135,85,217,167,153,185,50,66,251,216,213,113,158,126,161,82,183,27,189,147,66,36,18,42,199,15,29,182,77,156,94,99,200,75,128,23,80,170,138,213,218,228,252,208,9,7,55,176,117,117,33] -static let AppleWWDRCAG4_cer: [UInt8] = [48,130,4,85,48,130,3,61,160,3,2,1,2,2,20,19,220,119,149,82,113,229,61,198,50,232,204,255,229,33,243,204,197,206,210,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,48,49,50,49,54,49,57,51,54,48,52,90,23,13,51,48,49,50,49,48,48,48,48,48,48,48,90,48,117,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,11,48,9,6,3,85,4,11,12,2,71,52,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,208,31,120,170,122,39,50,176,70,95,231,23,118,216,160,157,14,41,142,173,61,50,165,196,107,55,201,228,65,145,106,183,121,113,93,12,52,4,96,117,247,174,67,143,71,196,134,30,8,232,191,214,57,82,47,30,103,252,113,241,130,109,60,126,6,82,118,157,44,188,213,67,233,177,180,188,64,58,120,81,93,81,161,37,225,190,108,145,157,107,33,89,24,65,213,15,141,109,65,42,57,74,33,224,144,159,78,19,79,208,140,154,50,184,215,106,146,30,37,106,164,50,206,34,25,133,5,96,220,2,74,242,90,235,119,121,2,125,192,151,84,108,146,142,118,1,230,70,143,229,230,42,251,162,176,173,24,173,109,51,133,56,35,139,234,138,150,237,159,174,102,79,163,12,64,39,109,149,208,98,136,217,67,41,39,253,237,164,191,83,46,144,21,101,60,217,46,98,100,51,29,108,106,221,142,33,170,164,95,21,198,48,237,95,230,140,54,146,148,183,220,57,2,0,251,100,140,212,12,129,242,63,213,52,151,135,117,38,194,111,174,3,99,33,12,123,212,27,177,98,197,2,156,189,253,175,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,91,217,250,29,231,154,26,11,163,153,118,34,80,134,62,145,200,91,119,168,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,3,130,1,1,0,63,86,61,158,229,182,195,121,230,69,32,104,189,191,115,139,44,18,158,2,227,174,128,34,140,4,30,195,82,200,112,128,168,251,206,167,176,213,66,68,130,3,130,79,6,252,59,73,20,251,216,116,82,133,175,167,157,33,231,1,18,3,159,205,64,88,208,1,215,191,50,131,43,83,88,40,60,238,156,159,84,118,61,100,39,198,126,141,29,56,77,45,174,129,230,185,165,184,156,137,148,247,159,199,135,165,81,102,52,27,57,113,57,36,227,135,103,239,165,177,104,123,140,238,61,247,174,182,123,226,210,255,223,97,198,106,117,73,149,34,68,168,4,252,148,184,11,46,57,17,73,18,209,229,129,234,89,0,79,91,60,90,54,218,122,34,115,9,9,105,205,192,124,234,226,36,254,152,68,184,248,239,178,113,63,26,93,212,93,126,51,77,156,29,36,190,0,240,144,3,88,153,65,61,49,90,98,64,175,57,168,81,67,146,171,4,168,156,194,77,177,75,210,171,124,74,95,235,157,59,188,79,136,64,6,19,255,144,23,138,8,71,41,232,98,152,41,165,79,17,5,105,58,207,242,159] -static let AppleWWDRCAG6_cer: [UInt8] = [48,130,3,22,48,130,2,156,160,3,2,1,2,2,20,34,193,161,71,10,116,115,105,239,83,134,18,201,198,159,61,56,243,108,215,48,10,6,8,42,134,72,206,61,4,3,3,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,51,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,30,23,13,50,49,48,51,49,55,50,48,51,55,49,48,90,23,13,51,54,48,51,49,57,48,48,48,48,48,48,90,48,117,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,11,48,9,6,3,85,4,11,12,2,71,54,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,118,48,16,6,7,42,134,72,206,61,2,1,6,5,43,129,4,0,34,3,98,0,4,110,196,10,11,222,15,174,85,166,101,121,215,130,220,115,117,82,75,241,61,18,25,137,224,13,17,169,158,9,247,55,163,211,240,147,4,111,177,67,139,134,193,152,248,66,157,157,255,178,174,143,23,247,6,112,165,214,176,190,111,58,215,145,135,34,120,231,29,192,72,254,220,56,31,154,106,143,116,125,202,113,74,255,196,100,86,231,136,6,205,129,145,161,34,26,72,163,129,250,48,129,247,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,187,176,222,161,88,51,136,154,164,138,153,222,190,189,235,175,218,203,36,171,48,70,6,8,43,6,1,5,5,7,1,1,4,58,48,56,48,54,6,8,43,6,1,5,5,7,48,1,134,42,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,103,51,48,55,6,3,85,29,31,4,48,48,46,48,44,160,42,160,40,134,38,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,97,112,112,108,101,114,111,111,116,99,97,103,51,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,63,47,148,35,81,211,80,201,154,40,61,237,176,124,229,207,165,144,98,153,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,10,6,8,42,134,72,206,61,4,3,3,3,104,0,48,101,2,48,64,94,20,170,228,140,138,162,3,2,62,220,56,247,64,90,7,174,251,9,161,6,37,123,159,64,31,196,169,145,157,232,36,163,136,43,78,158,227,19,109,117,87,155,28,92,197,249,2,49,0,211,72,252,90,173,149,239,54,185,49,83,116,228,80,194,55,223,44,239,21,85,81,79,140,49,88,144,189,247,131,172,117,198,120,249,17,141,177,128,242,71,152,38,118,189,39,12,104] -static let AppleWWDRCAG8_cer: [UInt8] = [48,130,4,85,48,130,3,61,160,3,2,1,2,2,20,84,181,11,175,121,13,141,127,140,175,104,76,86,47,80,105,10,26,186,95,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,98,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,19,10,65,112,112,108,101,32,73,110,99,46,49,38,48,36,6,3,85,4,11,19,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,22,48,20,6,3,85,4,3,19,13,65,112,112,108,101,32,82,111,111,116,32,67,65,48,30,23,13,50,51,48,54,50,48,50,51,51,55,49,53,90,23,13,50,53,48,49,50,52,48,48,48,48,48,48,90,48,117,49,11,48,9,6,3,85,4,6,19,2,85,83,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,11,12,2,71,56,49,68,48,66,6,3,85,4,3,12,59,65,112,112,108,101,32,87,111,114,108,100,119,105,100,101,32,68,101,118,101,108,111,112,101,114,32,82,101,108,97,116,105,111,110,115,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,48,130,1,34,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,208,64,16,212,8,249,82,33,99,79,60,104,247,212,156,130,2,140,131,104,188,183,141,127,136,231,66,77,44,239,34,165,194,137,222,189,12,215,77,97,80,45,57,228,48,115,165,210,213,104,154,51,242,239,217,42,173,46,31,3,186,248,165,241,66,11,87,46,70,198,208,88,211,112,95,247,178,55,239,106,31,62,191,137,57,194,173,254,245,5,251,88,150,49,200,135,44,213,35,186,117,176,44,245,171,160,186,242,32,12,76,235,36,99,105,233,34,64,240,142,88,91,222,100,123,137,27,81,18,4,224,23,178,89,205,223,241,231,206,175,44,50,232,105,193,208,8,126,29,162,71,115,209,75,59,253,185,133,220,71,167,40,130,121,41,72,137,2,40,226,193,236,44,31,91,134,252,216,182,203,113,192,115,1,75,252,5,17,17,108,1,3,52,90,246,129,194,94,31,124,20,14,222,63,107,33,203,79,245,215,97,230,132,3,146,188,231,37,41,158,205,91,12,193,219,227,196,58,217,118,87,172,47,56,20,25,200,183,177,162,85,79,95,78,142,25,89,169,218,253,114,218,176,4,33,5,2,3,1,0,1,163,129,239,48,129,236,48,18,6,3,85,29,19,1,1,255,4,8,48,6,1,1,255,2,1,0,48,31,6,3,85,29,35,4,24,48,22,128,20,43,208,105,71,148,118,9,254,244,107,141,46,64,166,247,71,77,127,8,94,48,68,6,8,43,6,1,5,5,7,1,1,4,56,48,54,48,52,6,8,43,6,1,5,5,7,48,1,134,40,104,116,116,112,58,47,47,111,99,115,112,46,97,112,112,108,101,46,99,111,109,47,111,99,115,112,48,51,45,97,112,112,108,101,114,111,111,116,99,97,48,46,6,3,85,29,31,4,39,48,37,48,35,160,33,160,31,134,29,104,116,116,112,58,47,47,99,114,108,46,97,112,112,108,101,46,99,111,109,47,114,111,111,116,46,99,114,108,48,29,6,3,85,29,14,4,22,4,20,181,189,188,128,196,12,227,56,164,244,183,173,35,179,239,68,206,185,90,133,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,16,6,10,42,134,72,134,247,99,100,6,2,1,4,2,5,0,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,130,1,1,0,76,179,235,122,57,148,74,149,102,250,22,49,234,13,138,143,93,66,56,198,7,205,232,201,34,172,252,8,66,126,95,147,95,49,42,168,34,193,118,25,43,238,174,114,233,189,86,207,73,36,146,8,247,205,25,117,195,249,26,39,13,14,220,41,141,63,182,219,165,79,76,114,196,96,145,137,17,126,36,149,67,34,96,103,188,223,255,171,229,60,22,23,157,130,20,78,157,244,117,254,80,185,173,5,178,184,121,246,149,214,16,229,246,83,244,207,35,230,119,15,236,184,75,105,248,226,158,2,49,217,142,217,202,190,99,94,95,225,160,105,206,193,205,110,73,163,120,97,175,57,60,106,75,10,52,37,100,213,48,181,60,171,221,17,129,57,113,232,192,195,88,128,17,16,26,17,210,194,188,89,240,138,217,53,115,192,230,109,228,201,125,98,20,62,130,2,169,16,105,55,121,97,111,240,70,148,62,53,245,171,172,99,208,216,94,89,87,105,209,184,75,110,93,212,95,19,156,112,78,37,17,220,36,44,30,22,158,150,90,4,237,69,238,58,238,103,93,143,195,134,176,245,76,31,104,16] -static let AppleRootCA_G3_cer: [UInt8] = [48,130,2,67,48,130,1,201,160,3,2,1,2,2,8,45,197,252,136,210,197,75,149,48,10,6,8,42,134,72,206,61,4,3,3,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,51,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,30,23,13,49,52,48,52,51,48,49,56,49,57,48,54,90,23,13,51,57,48,52,51,48,49,56,49,57,48,54,90,48,103,49,27,48,25,6,3,85,4,3,12,18,65,112,112,108,101,32,82,111,111,116,32,67,65,32,45,32,71,51,49,38,48,36,6,3,85,4,11,12,29,65,112,112,108,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117,116,104,111,114,105,116,121,49,19,48,17,6,3,85,4,10,12,10,65,112,112,108,101,32,73,110,99,46,49,11,48,9,6,3,85,4,6,19,2,85,83,48,118,48,16,6,7,42,134,72,206,61,2,1,6,5,43,129,4,0,34,3,98,0,4,152,233,47,61,64,114,164,237,147,34,114,129,19,28,221,16,149,241,197,163,78,113,220,20,22,217,14,229,166,5,42,119,100,123,95,78,56,211,187,28,68,181,127,245,31,182,50,98,93,201,233,132,91,79,48,79,17,90,0,253,88,88,12,165,245,15,44,77,7,71,19,117,218,151,151,151,111,49,92,237,43,157,123,32,59,216,185,84,217,94,153,164,58,81,10,49,163,66,48,64,48,29,6,3,85,29,14,4,22,4,20,187,176,222,161,88,51,136,154,164,138,153,222,190,189,235,175,218,203,36,171,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,255,48,14,6,3,85,29,15,1,1,255,4,4,3,2,1,6,48,10,6,8,42,134,72,206,61,4,3,3,3,104,0,48,101,2,49,0,131,233,193,196,22,94,26,93,52,24,217,237,239,244,108,14,0,70,75,184,223,178,70,17,197,15,253,230,122,140,161,166,107,206,194,3,212,156,245,147,198,116,184,106,223,170,35,21,2,48,109,102,138,16,202,212,13,212,79,205,141,67,62,180,138,99,165,51,110,227,109,218,23,183,100,31,200,83,38,249,136,98,116,57,11,23,91,203,81,168,12,232,24,3,231,162,178,40] -} \ No newline at end of file + static let AppleWWDRCAG2_cer: [UInt8] = [48, 130, 2, 247, 48, 130, 2, 124, 160, 3, 2, 1, 2, 2, 8, 111, 239, 216, 245, 233, 163, 167, 238, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 30, 23, 13, 49, 52, 48, 53, 48, 54, 50, 51, 52, 51, 50, 52, 90, 23, 13, 50, 57, 48, 53, 48, 54, 50, 51, 52, 51, 50, 52, 90, 48, 129, 128, 49, 52, 48, 50, 6, 3, 85, 4, 3, 12, 43, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 65, 32, 45, 32, 71, 50, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 221, 240, 183, 6, 75, 207, 221, 115, 4, 19, 196, 67, 137, 3, 147, 128, 251, 94, 246, 116, 173, 66, 97, 82, 88, 2, 38, 83, 25, 200, 99, 34, 7, 9, 82, 97, 202, 196, 217, 87, 239, 109, 38, 104, 139, 116, 145, 140, 196, 249, 128, 104, 40, 252, 9, 104, 240, 16, 218, 233, 208, 46, 201, 26, 163, 129, 247, 48, 129, 244, 48, 70, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 58, 48, 56, 48, 54, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 42, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 52, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 103, 51, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 132, 182, 132, 204, 58, 134, 98, 114, 22, 89, 148, 232, 26, 163, 189, 72, 223, 58, 223, 11, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 187, 176, 222, 161, 88, 51, 136, 154, 164, 138, 153, 222, 190, 189, 235, 175, 218, 203, 36, 171, 48, 55, 6, 3, 85, 29, 31, 4, 48, 48, 46, 48, 44, 160, 42, 160, 40, 134, 38, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 103, 51, 46, 99, 114, 108, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 15, 4, 2, 5, 0, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 105, 0, 48, 102, 2, 49, 0, 217, 177, 199, 49, 198, 35, 246, 79, 77, 208, 217, 71, 197, 125, 24, 105, 17, 135, 113, 39, 211, 104, 173, 224, 155, 101, 154, 190, 108, 223, 63, 70, 166, 144, 9, 190, 110, 161, 59, 44, 176, 81, 137, 65, 60, 135, 210, 191, 2, 49, 0, 252, 100, 82, 137, 75, 60, 93, 191, 107, 28, 194, 137, 152, 47, 114, 174, 181, 155, 170, 26, 11, 35, 84, 119, 84, 232, 21, 67, 162, 197, 18, 218, 151, 80, 115, 124, 94, 208, 110, 178, 92, 98, 80, 215, 81, 241, 58, 90] + static let AppleWWDRCAG3_cer: [UInt8] = [48, 130, 4, 81, 48, 130, 3, 57, 160, 3, 2, 1, 2, 2, 16, 124, 175, 105, 10, 37, 183, 57, 254, 123, 155, 68, 122, 193, 120, 197, 238, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 48, 48, 50, 49, 57, 49, 56, 49, 51, 52, 55, 90, 23, 13, 51, 48, 48, 50, 50, 48, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 51, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 216, 245, 137, 252, 168, 89, 11, 135, 199, 76, 145, 46, 45, 86, 144, 211, 120, 29, 164, 48, 233, 165, 72, 239, 11, 67, 191, 45, 132, 251, 36, 93, 69, 27, 229, 235, 89, 54, 18, 92, 84, 100, 158, 108, 98, 45, 180, 198, 151, 202, 204, 60, 246, 214, 6, 145, 252, 229, 2, 166, 28, 106, 180, 121, 213, 103, 203, 172, 233, 63, 7, 17, 225, 132, 188, 71, 29, 102, 142, 57, 162, 232, 180, 73, 237, 58, 210, 225, 16, 96, 122, 142, 147, 140, 202, 192, 218, 12, 192, 131, 208, 227, 249, 145, 214, 167, 140, 200, 193, 115, 226, 174, 70, 209, 98, 157, 146, 168, 144, 96, 55, 125, 104, 150, 205, 141, 224, 252, 155, 250, 120, 187, 227, 123, 175, 45, 23, 221, 91, 254, 128, 89, 35, 117, 23, 184, 18, 193, 237, 27, 229, 52, 206, 254, 34, 181, 158, 73, 176, 229, 85, 191, 143, 132, 162, 60, 168, 186, 197, 134, 149, 22, 228, 0, 201, 159, 3, 208, 204, 179, 58, 22, 123, 214, 5, 92, 157, 235, 71, 174, 13, 181, 45, 140, 14, 105, 77, 64, 208, 75, 76, 59, 4, 158, 141, 33, 177, 172, 46, 67, 84, 48, 206, 193, 138, 134, 148, 152, 75, 223, 106, 13, 63, 254, 251, 28, 174, 151, 23, 194, 120, 10, 48, 224, 95, 31, 84, 59, 73, 183, 37, 0, 26, 55, 130, 210, 86, 151, 165, 82, 73, 124, 96, 56, 155, 239, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 9, 254, 192, 21, 144, 249, 175, 100, 10, 146, 18, 185, 38, 40, 99, 12, 151, 236, 167, 178, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, 173, 101, 19, 232, 246, 224, 129, 119, 68, 2, 71, 66, 190, 95, 165, 57, 32, 234, 98, 169, 253, 197, 144, 201, 115, 19, 213, 158, 155, 208, 170, 15, 141, 141, 203, 237, 1, 207, 108, 40, 64, 91, 199, 85, 36, 65, 248, 252, 207, 193, 181, 35, 233, 220, 236, 241, 111, 202, 128, 29, 119, 194, 196, 97, 73, 37, 103, 175, 15, 202, 57, 37, 173, 211, 227, 122, 204, 51, 40, 13, 14, 46, 161, 87, 64, 115, 250, 230, 92, 174, 6, 81, 41, 237, 227, 133, 12, 79, 97, 220, 50, 22, 139, 119, 208, 68, 202, 93, 114, 3, 49, 70, 156, 174, 155, 64, 26, 250, 244, 224, 211, 62, 250, 47, 140, 102, 159, 151, 196, 84, 89, 239, 210, 72, 244, 7, 153, 73, 96, 89, 25, 199, 221, 148, 209, 192, 193, 108, 127, 120, 33, 239, 12, 235, 59, 108, 153, 130, 75, 82, 96, 56, 181, 57, 130, 109, 236, 82, 49, 83, 190, 15, 145, 76, 73, 73, 116, 143, 166, 81, 203, 132, 71, 78, 29, 117, 39, 110, 189, 249, 210, 92, 243, 127, 194, 108, 11, 9, 54, 226, 100, 228, 194, 55, 3, 20, 25, 213, 234, 106, 148, 170, 169, 219, 254, 246, 154, 8, 103, 139, 239, 43, 184, 170, 23, 73, 131, 175, 207, 203, 188, 233, 207, 234, 149, 113, 176, 180, 69, 162, 204, 229, 135, 170, 10, 195, 65, 58, 121, 92, 218, 80, 52, 157, 149, 59] + static let AppleWWDRCAG5_cer: [UInt8] = [48, 130, 4, 85, 48, 130, 3, 61, 160, 3, 2, 1, 2, 2, 20, 59, 126, 128, 10, 238, 211, 2, 161, 230, 236, 219, 151, 217, 202, 172, 40, 156, 241, 105, 148, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 48, 49, 50, 49, 54, 49, 57, 51, 56, 53, 54, 90, 23, 13, 51, 48, 49, 50, 49, 48, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 53, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 159, 93, 218, 31, 251, 250, 188, 208, 75, 34, 60, 199, 214, 38, 250, 23, 247, 244, 159, 30, 62, 100, 17, 102, 154, 239, 94, 190, 171, 52, 189, 170, 44, 33, 110, 214, 30, 148, 33, 133, 44, 116, 193, 14, 16, 97, 170, 60, 99, 74, 126, 74, 227, 200, 117, 214, 207, 194, 156, 8, 72, 123, 106, 185, 41, 177, 201, 102, 253, 200, 138, 22, 209, 178, 4, 60, 130, 186, 128, 108, 226, 255, 10, 114, 235, 172, 254, 59, 111, 72, 190, 158, 139, 17, 77, 149, 125, 178, 123, 144, 47, 2, 28, 78, 252, 73, 190, 215, 111, 181, 79, 190, 120, 198, 218, 222, 178, 205, 201, 217, 102, 17, 59, 90, 233, 9, 69, 115, 137, 80, 212, 78, 226, 104, 5, 126, 218, 117, 156, 75, 1, 174, 218, 227, 207, 109, 116, 77, 222, 83, 208, 213, 26, 56, 130, 58, 208, 157, 227, 93, 41, 123, 177, 129, 234, 41, 39, 11, 251, 96, 124, 134, 18, 251, 240, 98, 79, 6, 231, 76, 209, 31, 217, 109, 158, 237, 115, 218, 120, 33, 13, 157, 112, 217, 70, 87, 144, 95, 103, 132, 193, 115, 119, 10, 168, 98, 98, 182, 174, 112, 134, 187, 117, 35, 137, 173, 121, 246, 230, 164, 212, 253, 131, 38, 50, 10, 59, 36, 146, 91, 32, 161, 156, 209, 47, 128, 24, 155, 221, 60, 11, 231, 181, 253, 236, 128, 87, 15, 23, 158, 63, 43, 135, 39, 187, 247, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 25, 139, 151, 141, 74, 91, 97, 120, 87, 244, 165, 92, 53, 18, 138, 57, 8, 227, 176, 117, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, 90, 196, 53, 162, 217, 230, 10, 158, 82, 162, 0, 130, 34, 119, 205, 114, 47, 144, 249, 34, 175, 20, 37, 204, 170, 10, 66, 96, 146, 194, 189, 117, 29, 235, 76, 202, 21, 229, 126, 107, 64, 16, 94, 251, 91, 69, 116, 13, 240, 122, 125, 136, 145, 206, 222, 99, 139, 66, 137, 210, 24, 223, 65, 179, 88, 158, 6, 8, 135, 72, 221, 64, 175, 35, 213, 237, 235, 44, 96, 229, 235, 164, 127, 28, 233, 156, 131, 214, 148, 95, 76, 98, 57, 138, 78, 174, 19, 141, 125, 67, 184, 220, 94, 172, 190, 24, 64, 242, 230, 15, 44, 93, 19, 147, 241, 123, 101, 168, 194, 104, 72, 222, 255, 180, 150, 155, 12, 251, 50, 54, 158, 158, 13, 149, 95, 56, 10, 139, 150, 210, 18, 108, 183, 139, 11, 142, 215, 62, 236, 111, 1, 170, 206, 77, 69, 96, 219, 132, 113, 102, 98, 229, 25, 101, 48, 205, 138, 255, 69, 83, 251, 110, 251, 136, 119, 67, 195, 72, 99, 249, 247, 81, 179, 114, 94, 121, 226, 86, 207, 188, 187, 132, 185, 56, 90, 120, 174, 17, 72, 82, 187, 13, 53, 139, 148, 222, 204, 116, 154, 104, 245, 73, 96, 148, 172, 242, 168, 179, 21, 134, 144, 208, 204, 48, 67, 134, 211, 229, 112, 2, 81, 180, 129, 192, 168, 151, 212, 234, 234, 176, 140, 9, 64, 239, 56, 147, 178, 205, 34, 3, 235, 103, 67, 101, 200, 69] + static let AppleRootCA_G2_cer: [UInt8] = [48, 130, 5, 146, 48, 130, 3, 122, 160, 3, 2, 1, 2, 2, 8, 1, 224, 229, 181, 131, 103, 163, 224, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 12, 5, 0, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 50, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 30, 23, 13, 49, 52, 48, 52, 51, 48, 49, 56, 49, 48, 48, 57, 90, 23, 13, 51, 57, 48, 52, 51, 48, 49, 56, 49, 48, 48, 57, 90, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 50, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 130, 2, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 2, 15, 0, 48, 130, 2, 10, 2, 130, 2, 1, 0, 216, 17, 18, 72, 72, 218, 41, 138, 73, 197, 28, 199, 236, 110, 51, 109, 254, 77, 251, 224, 28, 222, 172, 94, 226, 54, 167, 36, 249, 127, 80, 107, 76, 206, 185, 48, 84, 39, 229, 179, 214, 237, 37, 230, 48, 182, 5, 55, 94, 20, 34, 17, 197, 232, 170, 27, 210, 251, 178, 210, 9, 149, 56, 164, 239, 42, 73, 140, 93, 62, 113, 102, 3, 56, 251, 22, 245, 133, 136, 228, 90, 146, 12, 4, 50, 242, 200, 64, 251, 82, 95, 159, 246, 192, 241, 227, 186, 69, 160, 80, 213, 18, 139, 242, 221, 222, 145, 134, 35, 240, 245, 182, 114, 46, 1, 218, 11, 246, 46, 57, 8, 95, 25, 161, 99, 65, 11, 28, 167, 148, 193, 134, 196, 83, 47, 118, 246, 10, 215, 12, 209, 131, 63, 26, 83, 25, 243, 87, 213, 39, 127, 252, 19, 184, 248, 146, 141, 252, 211, 40, 67, 60, 181, 104, 0, 37, 93, 39, 98, 211, 221, 85, 221, 68, 32, 144, 131, 53, 147, 197, 191, 184, 25, 251, 107, 227, 220, 8, 66, 230, 175, 109, 250, 158, 64, 202, 78, 133, 133, 120, 73, 177, 215, 195, 193, 48, 57, 50, 171, 126, 95, 170, 211, 139, 111, 159, 45, 26, 33, 104, 112, 103, 179, 163, 241, 152, 65, 109, 145, 124, 248, 215, 219, 168, 231, 95, 33, 26, 140, 51, 191, 49, 116, 183, 184, 209, 244, 224, 34, 244, 191, 114, 52, 223, 247, 129, 77, 113, 125, 81, 161, 226, 179, 240, 211, 40, 22, 115, 111, 205, 204, 173, 55, 125, 78, 235, 173, 64, 225, 63, 129, 253, 247, 61, 10, 62, 162, 241, 189, 49, 150, 41, 89, 220, 194, 25, 128, 140, 91, 116, 198, 44, 211, 16, 83, 38, 29, 20, 79, 196, 212, 129, 102, 60, 135, 103, 51, 39, 20, 8, 233, 180, 119, 132, 52, 82, 143, 137, 248, 104, 152, 23, 191, 195, 187, 170, 19, 147, 31, 93, 84, 47, 168, 199, 124, 251, 13, 20, 190, 21, 61, 36, 52, 242, 154, 220, 117, 65, 102, 34, 180, 1, 214, 11, 175, 144, 158, 12, 234, 98, 248, 155, 89, 60, 8, 226, 150, 52, 228, 99, 222, 188, 55, 212, 235, 12, 136, 3, 67, 11, 80, 175, 160, 52, 221, 80, 77, 21, 251, 90, 36, 216, 12, 250, 12, 99, 158, 31, 3, 177, 225, 238, 225, 170, 67, 244, 102, 101, 40, 55, 2, 49, 239, 1, 199, 30, 209, 204, 159, 109, 202, 84, 58, 64, 219, 206, 207, 79, 70, 139, 74, 101, 154, 106, 198, 104, 108, 215, 204, 153, 27, 71, 176, 114, 195, 119, 143, 196, 247, 97, 156, 116, 31, 206, 253, 107, 161, 194, 156, 148, 130, 171, 148, 162, 231, 189, 27, 186, 185, 112, 57, 149, 23, 197, 41, 243, 57, 88, 52, 245, 196, 164, 198, 123, 96, 185, 102, 67, 80, 63, 110, 97, 252, 14, 249, 134, 170, 96, 12, 67, 75, 149, 2, 3, 1, 0, 1, 163, 66, 48, 64, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 196, 153, 19, 108, 24, 3, 194, 123, 192, 163, 160, 13, 127, 114, 128, 122, 28, 119, 38, 141, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 12, 5, 0, 3, 130, 2, 1, 0, 81, 166, 243, 226, 244, 184, 61, 147, 191, 45, 206, 15, 187, 91, 225, 85, 20, 78, 78, 209, 229, 206, 121, 93, 129, 127, 254, 182, 240, 135, 51, 248, 239, 148, 229, 126, 220, 106, 121, 167, 28, 190, 240, 148, 183, 166, 209, 48, 156, 200, 13, 10, 117, 158, 125, 146, 149, 126, 24, 157, 126, 194, 113, 105, 124, 20, 234, 207, 131, 14, 228, 20, 66, 158, 116, 14, 16, 205, 171, 26, 186, 17, 97, 129, 120, 216, 241, 181, 69, 64, 120, 171, 168, 192, 206, 251, 125, 99, 55, 104, 246, 231, 251, 175, 198, 195, 75, 236, 31, 54, 38, 19, 84, 134, 148, 114, 178, 234, 2, 237, 139, 109, 228, 12, 166, 144, 192, 87, 117, 207, 140, 66, 125, 92, 230, 49, 125, 243, 201, 178, 146, 105, 70, 14, 136, 248, 227, 45, 66, 178, 56, 168, 166, 25, 141, 241, 159, 205, 238, 106, 101, 188, 26, 176, 37, 189, 167, 41, 253, 244, 62, 162, 117, 73, 191, 158, 219, 201, 247, 167, 30, 99, 153, 225, 92, 70, 255, 146, 5, 140, 250, 30, 32, 249, 134, 148, 86, 37, 229, 180, 87, 56, 157, 235, 136, 100, 20, 33, 73, 33, 57, 191, 98, 102, 169, 177, 162, 202, 111, 63, 33, 96, 197, 137, 212, 69, 54, 200, 152, 124, 189, 246, 254, 153, 73, 128, 59, 44, 210, 166, 167, 136, 3, 4, 49, 25, 183, 182, 58, 97, 69, 250, 201, 242, 35, 200, 99, 115, 191, 86, 137, 49, 176, 217, 124, 98, 167, 123, 21, 168, 136, 138, 171, 56, 64, 194, 204, 18, 255, 21, 227, 240, 55, 223, 55, 114, 203, 204, 152, 230, 191, 162, 188, 250, 38, 138, 113, 86, 215, 231, 36, 27, 72, 68, 62, 158, 252, 159, 201, 204, 26, 236, 67, 60, 1, 188, 52, 120, 200, 105, 245, 198, 230, 86, 236, 6, 9, 54, 144, 235, 20, 74, 27, 94, 201, 136, 35, 218, 3, 48, 145, 11, 184, 54, 62, 249, 231, 181, 40, 111, 190, 63, 236, 60, 143, 101, 29, 229, 192, 30, 135, 164, 170, 186, 152, 253, 146, 227, 108, 38, 119, 221, 6, 180, 100, 6, 135, 244, 78, 214, 186, 74, 170, 22, 168, 244, 5, 103, 102, 150, 186, 226, 85, 121, 195, 44, 93, 73, 143, 128, 73, 43, 138, 18, 199, 118, 128, 81, 223, 186, 189, 101, 93, 62, 55, 71, 99, 49, 233, 229, 244, 197, 63, 75, 173, 4, 138, 122, 113, 44, 175, 9, 67, 55, 15, 168, 227, 50, 79, 244, 69, 182, 109, 151, 54, 236, 132, 245, 10, 1, 234, 23, 187, 133, 141, 66, 147, 112, 195, 80, 229, 20, 139, 191, 63, 195, 65, 15, 221, 34, 4, 35, 8, 138, 186, 109, 113, 68, 171, 115, 9, 58, 201, 249, 82, 128, 9, 223, 186, 233, 230, 22, 202, 46, 46, 76, 178, 211, 220, 229, 4, 84, 178, 212, 52, 128, 50, 181, 188, 15, 23, 225] + static let AppleComputerRootCertificate_cer: [UInt8] = [48, 130, 5, 186, 48, 130, 4, 162, 160, 3, 2, 1, 2, 2, 1, 1, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 48, 129, 134, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 29, 48, 27, 6, 3, 85, 4, 10, 19, 20, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 44, 32, 73, 110, 99, 46, 49, 45, 48, 43, 6, 3, 85, 4, 11, 19, 36, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 41, 48, 39, 6, 3, 85, 4, 3, 19, 32, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 48, 30, 23, 13, 48, 53, 48, 50, 49, 48, 48, 48, 49, 56, 49, 52, 90, 23, 13, 50, 53, 48, 50, 49, 48, 48, 48, 49, 56, 49, 52, 90, 48, 129, 134, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 29, 48, 27, 6, 3, 85, 4, 10, 19, 20, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 44, 32, 73, 110, 99, 46, 49, 45, 48, 43, 6, 3, 85, 4, 11, 19, 36, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 41, 48, 39, 6, 3, 85, 4, 3, 19, 32, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 228, 145, 169, 9, 31, 145, 219, 30, 71, 80, 235, 5, 237, 94, 121, 132, 45, 235, 54, 162, 87, 76, 85, 236, 139, 25, 137, 222, 249, 75, 108, 245, 7, 171, 34, 48, 2, 232, 24, 62, 248, 80, 9, 211, 127, 65, 168, 152, 249, 209, 202, 102, 156, 36, 107, 17, 208, 163, 187, 228, 27, 42, 195, 31, 149, 158, 122, 12, 164, 71, 139, 91, 212, 22, 55, 51, 203, 196, 15, 77, 206, 20, 105, 209, 201, 25, 114, 245, 93, 14, 213, 127, 95, 155, 242, 37, 3, 186, 85, 143, 77, 93, 13, 241, 100, 53, 35, 21, 75, 21, 89, 29, 179, 148, 247, 246, 156, 158, 207, 80, 186, 193, 88, 80, 103, 143, 8, 180, 32, 247, 203, 172, 44, 32, 111, 112, 182, 63, 1, 48, 140, 183, 67, 207, 15, 157, 61, 243, 43, 73, 40, 26, 200, 254, 206, 181, 185, 14, 217, 94, 28, 214, 203, 61, 181, 58, 173, 244, 15, 14, 0, 146, 11, 177, 33, 22, 46, 116, 213, 60, 13, 219, 98, 22, 171, 163, 113, 146, 71, 83, 85, 193, 175, 47, 65, 179, 248, 251, 227, 112, 205, 230, 163, 76, 69, 126, 31, 76, 107, 80, 150, 65, 137, 196, 116, 98, 11, 16, 131, 65, 135, 51, 138, 129, 177, 48, 88, 236, 90, 4, 50, 140, 104, 179, 143, 29, 222, 101, 115, 255, 103, 94, 101, 188, 73, 216, 118, 159, 51, 20, 101, 161, 119, 148, 201, 45, 2, 3, 1, 0, 1, 163, 130, 2, 47, 48, 130, 2, 43, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 130, 1, 41, 6, 3, 85, 29, 32, 4, 130, 1, 32, 48, 130, 1, 28, 48, 130, 1, 24, 6, 9, 42, 134, 72, 134, 247, 99, 100, 5, 1, 48, 130, 1, 9, 48, 65, 6, 8, 43, 6, 1, 5, 5, 7, 2, 1, 22, 53, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 97, 117, 116, 104, 111, 114, 105, 116, 121, 47, 116, 101, 114, 109, 115, 46, 104, 116, 109, 108, 48, 129, 195, 6, 8, 43, 6, 1, 5, 5, 7, 2, 2, 48, 129, 182, 26, 129, 179, 82, 101, 108, 105, 97, 110, 99, 101, 32, 111, 110, 32, 116, 104, 105, 115, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 98, 121, 32, 97, 110, 121, 32, 112, 97, 114, 116, 121, 32, 97, 115, 115, 117, 109, 101, 115, 32, 97, 99, 99, 101, 112, 116, 97, 110, 99, 101, 32, 111, 102, 32, 116, 104, 101, 32, 116, 104, 101, 110, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, 115, 116, 97, 110, 100, 97, 114, 100, 32, 116, 101, 114, 109, 115, 32, 97, 110, 100, 32, 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 32, 111, 102, 32, 117, 115, 101, 44, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 112, 111, 108, 105, 99, 121, 32, 97, 110, 100, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 112, 114, 97, 99, 116, 105, 99, 101, 32, 115, 116, 97, 116, 101, 109, 101, 110, 116, 115, 46, 48, 68, 6, 3, 85, 29, 31, 4, 61, 48, 59, 48, 57, 160, 55, 160, 53, 134, 51, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 97, 117, 116, 104, 111, 114, 105, 116, 121, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 85, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 73, 48, 71, 48, 69, 6, 8, 43, 6, 1, 5, 5, 7, 48, 2, 134, 57, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 97, 117, 116, 104, 111, 114, 105, 116, 121, 47, 99, 97, 115, 105, 103, 110, 101, 114, 115, 46, 104, 116, 109, 108, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 3, 130, 1, 1, 0, 157, 218, 45, 40, 88, 47, 125, 118, 4, 185, 4, 211, 62, 206, 183, 102, 99, 78, 143, 47, 212, 254, 75, 173, 114, 189, 163, 57, 198, 82, 77, 5, 152, 82, 245, 137, 81, 1, 36, 121, 190, 26, 50, 247, 229, 68, 139, 75, 68, 7, 57, 130, 214, 90, 202, 180, 32, 94, 217, 174, 21, 93, 29, 140, 29, 50, 191, 56, 49, 98, 72, 93, 199, 225, 144, 177, 248, 36, 64, 248, 95, 88, 155, 81, 93, 87, 157, 193, 229, 255, 60, 204, 114, 33, 110, 196, 233, 233, 161, 119, 215, 44, 23, 38, 195, 63, 235, 154, 232, 11, 3, 186, 233, 179, 74, 114, 235, 51, 9, 91, 173, 230, 98, 49, 106, 232, 175, 47, 213, 175, 30, 87, 118, 143, 127, 55, 45, 46, 2, 92, 221, 99, 201, 242, 113, 184, 38, 64, 223, 21, 141, 117, 68, 63, 121, 189, 230, 29, 153, 225, 67, 44, 62, 173, 111, 190, 185, 164, 254, 14, 53, 25, 81, 99, 177, 195, 222, 181, 146, 62, 81, 120, 1, 115, 138, 164, 35, 202, 164, 136, 241, 30, 92, 31, 65, 22, 45, 126, 149, 10, 170, 233, 137, 65, 152, 27, 26, 221, 203, 32, 191, 71, 94, 12, 38, 197, 85, 53, 77, 198, 48, 139, 153, 103, 20, 199, 9, 31, 186, 71, 199, 218, 1, 9, 135, 36, 66, 149, 189, 19, 96, 25, 10, 239, 234, 127, 14, 110, 205, 193, 68, 67, 58, 74, 213, 227] + static let AppleWWDRCAG7_cer: [UInt8] = [48, 130, 4, 85, 48, 130, 3, 61, 160, 3, 2, 1, 2, 2, 20, 52, 24, 88, 255, 1, 254, 6, 63, 142, 241, 159, 31, 233, 60, 1, 180, 193, 70, 255, 201, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 50, 49, 49, 49, 55, 50, 48, 52, 48, 53, 51, 90, 23, 13, 50, 51, 49, 49, 49, 55, 50, 48, 52, 48, 53, 50, 90, 48, 117, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 55, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 172, 174, 209, 211, 182, 138, 177, 27, 40, 149, 173, 222, 81, 81, 76, 63, 51, 225, 78, 92, 175, 179, 252, 2, 210, 101, 79, 42, 212, 116, 104, 140, 117, 23, 101, 207, 40, 228, 72, 9, 152, 113, 82, 50, 44, 22, 78, 120, 142, 146, 86, 100, 169, 221, 139, 205, 226, 212, 199, 59, 162, 18, 69, 55, 2, 25, 98, 100, 47, 127, 97, 198, 211, 89, 34, 191, 171, 249, 20, 163, 237, 182, 158, 153, 186, 47, 241, 177, 220, 48, 66, 79, 182, 182, 178, 198, 116, 170, 98, 86, 187, 237, 68, 54, 15, 209, 229, 32, 116, 147, 87, 58, 93, 158, 220, 1, 252, 120, 111, 105, 22, 53, 195, 110, 1, 194, 158, 114, 212, 113, 54, 177, 118, 9, 122, 190, 13, 42, 151, 241, 176, 94, 11, 27, 18, 173, 43, 171, 7, 223, 99, 45, 245, 136, 233, 50, 18, 162, 85, 88, 67, 118, 60, 61, 23, 128, 31, 41, 219, 177, 169, 159, 171, 150, 5, 157, 21, 220, 221, 219, 78, 15, 231, 19, 124, 90, 43, 46, 2, 65, 246, 238, 122, 106, 182, 115, 96, 247, 151, 25, 20, 139, 149, 51, 56, 147, 218, 0, 37, 54, 174, 85, 90, 124, 159, 249, 244, 98, 4, 7, 116, 233, 29, 167, 149, 87, 35, 172, 43, 36, 218, 100, 79, 40, 114, 233, 150, 176, 8, 60, 136, 27, 20, 99, 67, 215, 137, 174, 152, 193, 242, 45, 142, 227, 81, 37, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 93, 66, 16, 108, 27, 187, 199, 82, 151, 78, 68, 189, 19, 39, 185, 58, 18, 119, 131, 43, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 3, 130, 1, 1, 0, 82, 163, 8, 41, 19, 101, 183, 181, 31, 230, 52, 3, 237, 246, 24, 119, 188, 61, 202, 39, 181, 112, 236, 236, 108, 51, 75, 246, 153, 37, 148, 7, 158, 33, 51, 3, 106, 245, 125, 10, 46, 43, 223, 8, 169, 130, 222, 74, 127, 225, 231, 11, 75, 5, 184, 39, 152, 73, 221, 193, 12, 134, 215, 129, 100, 174, 130, 156, 196, 69, 241, 234, 143, 28, 34, 48, 227, 162, 37, 97, 68, 137, 254, 133, 122, 86, 240, 114, 146, 124, 12, 68, 84, 36, 183, 181, 164, 159, 38, 240, 50, 249, 87, 157, 106, 121, 108, 64, 237, 15, 52, 6, 6, 66, 255, 216, 14, 49, 101, 109, 230, 46, 1, 217, 6, 191, 197, 202, 13, 174, 71, 212, 5, 23, 136, 60, 233, 156, 228, 25, 100, 109, 138, 148, 173, 17, 220, 1, 246, 229, 120, 175, 173, 232, 112, 215, 13, 93, 129, 62, 70, 42, 44, 174, 36, 161, 199, 210, 224, 125, 191, 29, 245, 54, 107, 197, 222, 169, 10, 154, 128, 177, 17, 94, 178, 100, 126, 179, 193, 87, 204, 194, 108, 89, 153, 183, 244, 176, 221, 49, 218, 72, 214, 106, 129, 238, 178, 139, 80, 53, 22, 230, 231, 92, 113, 98, 110, 176, 242, 81, 226, 168, 109, 248, 42, 203, 104, 115, 198, 166, 196, 26, 67, 73, 1, 62, 169, 169, 0, 138, 134, 108, 131, 136, 210, 92, 112, 87, 122, 218, 248, 118, 204, 25, 213, 176] + static let AppleIncRootCertificate_cer: [UInt8] = [48, 130, 4, 187, 48, 130, 3, 163, 160, 3, 2, 1, 2, 2, 1, 2, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 48, 54, 48, 52, 50, 53, 50, 49, 52, 48, 51, 54, 90, 23, 13, 51, 53, 48, 50, 48, 57, 50, 49, 52, 48, 51, 54, 90, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 228, 145, 169, 9, 31, 145, 219, 30, 71, 80, 235, 5, 237, 94, 121, 132, 45, 235, 54, 162, 87, 76, 85, 236, 139, 25, 137, 222, 249, 75, 108, 245, 7, 171, 34, 48, 2, 232, 24, 62, 248, 80, 9, 211, 127, 65, 168, 152, 249, 209, 202, 102, 156, 36, 107, 17, 208, 163, 187, 228, 27, 42, 195, 31, 149, 158, 122, 12, 164, 71, 139, 91, 212, 22, 55, 51, 203, 196, 15, 77, 206, 20, 105, 209, 201, 25, 114, 245, 93, 14, 213, 127, 95, 155, 242, 37, 3, 186, 85, 143, 77, 93, 13, 241, 100, 53, 35, 21, 75, 21, 89, 29, 179, 148, 247, 246, 156, 158, 207, 80, 186, 193, 88, 80, 103, 143, 8, 180, 32, 247, 203, 172, 44, 32, 111, 112, 182, 63, 1, 48, 140, 183, 67, 207, 15, 157, 61, 243, 43, 73, 40, 26, 200, 254, 206, 181, 185, 14, 217, 94, 28, 214, 203, 61, 181, 58, 173, 244, 15, 14, 0, 146, 11, 177, 33, 22, 46, 116, 213, 60, 13, 219, 98, 22, 171, 163, 113, 146, 71, 83, 85, 193, 175, 47, 65, 179, 248, 251, 227, 112, 205, 230, 163, 76, 69, 126, 31, 76, 107, 80, 150, 65, 137, 196, 116, 98, 11, 16, 131, 65, 135, 51, 138, 129, 177, 48, 88, 236, 90, 4, 50, 140, 104, 179, 143, 29, 222, 101, 115, 255, 103, 94, 101, 188, 73, 216, 118, 159, 51, 20, 101, 161, 119, 148, 201, 45, 2, 3, 1, 0, 1, 163, 130, 1, 122, 48, 130, 1, 118, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 130, 1, 17, 6, 3, 85, 29, 32, 4, 130, 1, 8, 48, 130, 1, 4, 48, 130, 1, 0, 6, 9, 42, 134, 72, 134, 247, 99, 100, 5, 1, 48, 129, 242, 48, 42, 6, 8, 43, 6, 1, 5, 5, 7, 2, 1, 22, 30, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 97, 112, 112, 108, 101, 99, 97, 47, 48, 129, 195, 6, 8, 43, 6, 1, 5, 5, 7, 2, 2, 48, 129, 182, 26, 129, 179, 82, 101, 108, 105, 97, 110, 99, 101, 32, 111, 110, 32, 116, 104, 105, 115, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 98, 121, 32, 97, 110, 121, 32, 112, 97, 114, 116, 121, 32, 97, 115, 115, 117, 109, 101, 115, 32, 97, 99, 99, 101, 112, 116, 97, 110, 99, 101, 32, 111, 102, 32, 116, 104, 101, 32, 116, 104, 101, 110, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, 115, 116, 97, 110, 100, 97, 114, 100, 32, 116, 101, 114, 109, 115, 32, 97, 110, 100, 32, 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 32, 111, 102, 32, 117, 115, 101, 44, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 112, 111, 108, 105, 99, 121, 32, 97, 110, 100, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 112, 114, 97, 99, 116, 105, 99, 101, 32, 115, 116, 97, 116, 101, 109, 101, 110, 116, 115, 46, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 3, 130, 1, 1, 0, 92, 54, 153, 76, 45, 120, 183, 237, 140, 155, 220, 243, 119, 155, 242, 118, 210, 119, 48, 79, 193, 31, 133, 131, 133, 27, 153, 61, 71, 55, 242, 169, 155, 64, 142, 44, 212, 177, 144, 18, 216, 190, 244, 115, 155, 238, 210, 100, 15, 203, 121, 79, 52, 216, 162, 62, 249, 120, 255, 107, 200, 7, 236, 125, 57, 131, 139, 83, 32, 211, 56, 196, 177, 191, 154, 79, 10, 107, 255, 43, 252, 89, 167, 5, 9, 124, 23, 64, 86, 17, 30, 116, 211, 183, 139, 35, 59, 71, 163, 213, 111, 36, 226, 235, 209, 183, 112, 223, 15, 69, 225, 39, 202, 241, 109, 120, 237, 231, 181, 23, 23, 168, 220, 126, 34, 53, 202, 37, 213, 217, 15, 214, 107, 212, 162, 36, 35, 17, 247, 161, 172, 143, 115, 129, 96, 198, 27, 91, 9, 47, 146, 178, 248, 68, 72, 240, 96, 56, 158, 21, 245, 61, 38, 103, 32, 138, 51, 106, 247, 13, 130, 207, 222, 235, 163, 47, 249, 83, 106, 91, 100, 192, 99, 51, 119, 247, 58, 7, 44, 86, 235, 218, 15, 33, 14, 218, 186, 115, 25, 79, 181, 217, 54, 127, 193, 135, 85, 217, 167, 153, 185, 50, 66, 251, 216, 213, 113, 158, 126, 161, 82, 183, 27, 189, 147, 66, 36, 18, 42, 199, 15, 29, 182, 77, 156, 94, 99, 200, 75, 128, 23, 80, 170, 138, 213, 218, 228, 252, 208, 9, 7, 55, 176, 117, 117, 33] + static let AppleWWDRCAG4_cer: [UInt8] = [48, 130, 4, 85, 48, 130, 3, 61, 160, 3, 2, 1, 2, 2, 20, 19, 220, 119, 149, 82, 113, 229, 61, 198, 50, 232, 204, 255, 229, 33, 243, 204, 197, 206, 210, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 48, 49, 50, 49, 54, 49, 57, 51, 54, 48, 52, 90, 23, 13, 51, 48, 49, 50, 49, 48, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 52, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 208, 31, 120, 170, 122, 39, 50, 176, 70, 95, 231, 23, 118, 216, 160, 157, 14, 41, 142, 173, 61, 50, 165, 196, 107, 55, 201, 228, 65, 145, 106, 183, 121, 113, 93, 12, 52, 4, 96, 117, 247, 174, 67, 143, 71, 196, 134, 30, 8, 232, 191, 214, 57, 82, 47, 30, 103, 252, 113, 241, 130, 109, 60, 126, 6, 82, 118, 157, 44, 188, 213, 67, 233, 177, 180, 188, 64, 58, 120, 81, 93, 81, 161, 37, 225, 190, 108, 145, 157, 107, 33, 89, 24, 65, 213, 15, 141, 109, 65, 42, 57, 74, 33, 224, 144, 159, 78, 19, 79, 208, 140, 154, 50, 184, 215, 106, 146, 30, 37, 106, 164, 50, 206, 34, 25, 133, 5, 96, 220, 2, 74, 242, 90, 235, 119, 121, 2, 125, 192, 151, 84, 108, 146, 142, 118, 1, 230, 70, 143, 229, 230, 42, 251, 162, 176, 173, 24, 173, 109, 51, 133, 56, 35, 139, 234, 138, 150, 237, 159, 174, 102, 79, 163, 12, 64, 39, 109, 149, 208, 98, 136, 217, 67, 41, 39, 253, 237, 164, 191, 83, 46, 144, 21, 101, 60, 217, 46, 98, 100, 51, 29, 108, 106, 221, 142, 33, 170, 164, 95, 21, 198, 48, 237, 95, 230, 140, 54, 146, 148, 183, 220, 57, 2, 0, 251, 100, 140, 212, 12, 129, 242, 63, 213, 52, 151, 135, 117, 38, 194, 111, 174, 3, 99, 33, 12, 123, 212, 27, 177, 98, 197, 2, 156, 189, 253, 175, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 91, 217, 250, 29, 231, 154, 26, 11, 163, 153, 118, 34, 80, 134, 62, 145, 200, 91, 119, 168, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, 63, 86, 61, 158, 229, 182, 195, 121, 230, 69, 32, 104, 189, 191, 115, 139, 44, 18, 158, 2, 227, 174, 128, 34, 140, 4, 30, 195, 82, 200, 112, 128, 168, 251, 206, 167, 176, 213, 66, 68, 130, 3, 130, 79, 6, 252, 59, 73, 20, 251, 216, 116, 82, 133, 175, 167, 157, 33, 231, 1, 18, 3, 159, 205, 64, 88, 208, 1, 215, 191, 50, 131, 43, 83, 88, 40, 60, 238, 156, 159, 84, 118, 61, 100, 39, 198, 126, 141, 29, 56, 77, 45, 174, 129, 230, 185, 165, 184, 156, 137, 148, 247, 159, 199, 135, 165, 81, 102, 52, 27, 57, 113, 57, 36, 227, 135, 103, 239, 165, 177, 104, 123, 140, 238, 61, 247, 174, 182, 123, 226, 210, 255, 223, 97, 198, 106, 117, 73, 149, 34, 68, 168, 4, 252, 148, 184, 11, 46, 57, 17, 73, 18, 209, 229, 129, 234, 89, 0, 79, 91, 60, 90, 54, 218, 122, 34, 115, 9, 9, 105, 205, 192, 124, 234, 226, 36, 254, 152, 68, 184, 248, 239, 178, 113, 63, 26, 93, 212, 93, 126, 51, 77, 156, 29, 36, 190, 0, 240, 144, 3, 88, 153, 65, 61, 49, 90, 98, 64, 175, 57, 168, 81, 67, 146, 171, 4, 168, 156, 194, 77, 177, 75, 210, 171, 124, 74, 95, 235, 157, 59, 188, 79, 136, 64, 6, 19, 255, 144, 23, 138, 8, 71, 41, 232, 98, 152, 41, 165, 79, 17, 5, 105, 58, 207, 242, 159] + static let AppleWWDRCAG6_cer: [UInt8] = [48, 130, 3, 22, 48, 130, 2, 156, 160, 3, 2, 1, 2, 2, 20, 34, 193, 161, 71, 10, 116, 115, 105, 239, 83, 134, 18, 201, 198, 159, 61, 56, 243, 108, 215, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 30, 23, 13, 50, 49, 48, 51, 49, 55, 50, 48, 51, 55, 49, 48, 90, 23, 13, 51, 54, 48, 51, 49, 57, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 54, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 118, 48, 16, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 5, 43, 129, 4, 0, 34, 3, 98, 0, 4, 110, 196, 10, 11, 222, 15, 174, 85, 166, 101, 121, 215, 130, 220, 115, 117, 82, 75, 241, 61, 18, 25, 137, 224, 13, 17, 169, 158, 9, 247, 55, 163, 211, 240, 147, 4, 111, 177, 67, 139, 134, 193, 152, 248, 66, 157, 157, 255, 178, 174, 143, 23, 247, 6, 112, 165, 214, 176, 190, 111, 58, 215, 145, 135, 34, 120, 231, 29, 192, 72, 254, 220, 56, 31, 154, 106, 143, 116, 125, 202, 113, 74, 255, 196, 100, 86, 231, 136, 6, 205, 129, 145, 161, 34, 26, 72, 163, 129, 250, 48, 129, 247, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 187, 176, 222, 161, 88, 51, 136, 154, 164, 138, 153, 222, 190, 189, 235, 175, 218, 203, 36, 171, 48, 70, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 58, 48, 56, 48, 54, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 42, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 103, 51, 48, 55, 6, 3, 85, 29, 31, 4, 48, 48, 46, 48, 44, 160, 42, 160, 40, 134, 38, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 103, 51, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 63, 47, 148, 35, 81, 211, 80, 201, 154, 40, 61, 237, 176, 124, 229, 207, 165, 144, 98, 153, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, 3, 104, 0, 48, 101, 2, 48, 64, 94, 20, 170, 228, 140, 138, 162, 3, 2, 62, 220, 56, 247, 64, 90, 7, 174, 251, 9, 161, 6, 37, 123, 159, 64, 31, 196, 169, 145, 157, 232, 36, 163, 136, 43, 78, 158, 227, 19, 109, 117, 87, 155, 28, 92, 197, 249, 2, 49, 0, 211, 72, 252, 90, 173, 149, 239, 54, 185, 49, 83, 116, 228, 80, 194, 55, 223, 44, 239, 21, 85, 81, 79, 140, 49, 88, 144, 189, 247, 131, 172, 117, 198, 120, 249, 17, 141, 177, 128, 242, 71, 152, 38, 118, 189, 39, 12, 104] + static let AppleWWDRCAG8_cer: [UInt8] = [48, 130, 4, 85, 48, 130, 3, 61, 160, 3, 2, 1, 2, 2, 20, 84, 181, 11, 175, 121, 13, 141, 127, 140, 175, 104, 76, 86, 47, 80, 105, 10, 26, 186, 95, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 38, 48, 36, 6, 3, 85, 4, 11, 19, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 48, 30, 23, 13, 50, 51, 48, 54, 50, 48, 50, 51, 51, 55, 49, 53, 90, 23, 13, 50, 53, 48, 49, 50, 52, 48, 48, 48, 48, 48, 48, 90, 48, 117, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 11, 12, 2, 71, 56, 49, 68, 48, 66, 6, 3, 85, 4, 3, 12, 59, 65, 112, 112, 108, 101, 32, 87, 111, 114, 108, 100, 119, 105, 100, 101, 32, 68, 101, 118, 101, 108, 111, 112, 101, 114, 32, 82, 101, 108, 97, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 208, 64, 16, 212, 8, 249, 82, 33, 99, 79, 60, 104, 247, 212, 156, 130, 2, 140, 131, 104, 188, 183, 141, 127, 136, 231, 66, 77, 44, 239, 34, 165, 194, 137, 222, 189, 12, 215, 77, 97, 80, 45, 57, 228, 48, 115, 165, 210, 213, 104, 154, 51, 242, 239, 217, 42, 173, 46, 31, 3, 186, 248, 165, 241, 66, 11, 87, 46, 70, 198, 208, 88, 211, 112, 95, 247, 178, 55, 239, 106, 31, 62, 191, 137, 57, 194, 173, 254, 245, 5, 251, 88, 150, 49, 200, 135, 44, 213, 35, 186, 117, 176, 44, 245, 171, 160, 186, 242, 32, 12, 76, 235, 36, 99, 105, 233, 34, 64, 240, 142, 88, 91, 222, 100, 123, 137, 27, 81, 18, 4, 224, 23, 178, 89, 205, 223, 241, 231, 206, 175, 44, 50, 232, 105, 193, 208, 8, 126, 29, 162, 71, 115, 209, 75, 59, 253, 185, 133, 220, 71, 167, 40, 130, 121, 41, 72, 137, 2, 40, 226, 193, 236, 44, 31, 91, 134, 252, 216, 182, 203, 113, 192, 115, 1, 75, 252, 5, 17, 17, 108, 1, 3, 52, 90, 246, 129, 194, 94, 31, 124, 20, 14, 222, 63, 107, 33, 203, 79, 245, 215, 97, 230, 132, 3, 146, 188, 231, 37, 41, 158, 205, 91, 12, 193, 219, 227, 196, 58, 217, 118, 87, 172, 47, 56, 20, 25, 200, 183, 177, 162, 85, 79, 95, 78, 142, 25, 89, 169, 218, 253, 114, 218, 176, 4, 33, 5, 2, 3, 1, 0, 1, 163, 129, 239, 48, 129, 236, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 0, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 43, 208, 105, 71, 148, 118, 9, 254, 244, 107, 141, 46, 64, 166, 247, 71, 77, 127, 8, 94, 48, 68, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 56, 48, 54, 48, 52, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 40, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 51, 45, 97, 112, 112, 108, 101, 114, 111, 111, 116, 99, 97, 48, 46, 6, 3, 85, 29, 31, 4, 39, 48, 37, 48, 35, 160, 33, 160, 31, 134, 29, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 114, 111, 111, 116, 46, 99, 114, 108, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 181, 189, 188, 128, 196, 12, 227, 56, 164, 244, 183, 173, 35, 179, 239, 68, 206, 185, 90, 133, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 16, 6, 10, 42, 134, 72, 134, 247, 99, 100, 6, 2, 1, 4, 2, 5, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, 0, 3, 130, 1, 1, 0, 76, 179, 235, 122, 57, 148, 74, 149, 102, 250, 22, 49, 234, 13, 138, 143, 93, 66, 56, 198, 7, 205, 232, 201, 34, 172, 252, 8, 66, 126, 95, 147, 95, 49, 42, 168, 34, 193, 118, 25, 43, 238, 174, 114, 233, 189, 86, 207, 73, 36, 146, 8, 247, 205, 25, 117, 195, 249, 26, 39, 13, 14, 220, 41, 141, 63, 182, 219, 165, 79, 76, 114, 196, 96, 145, 137, 17, 126, 36, 149, 67, 34, 96, 103, 188, 223, 255, 171, 229, 60, 22, 23, 157, 130, 20, 78, 157, 244, 117, 254, 80, 185, 173, 5, 178, 184, 121, 246, 149, 214, 16, 229, 246, 83, 244, 207, 35, 230, 119, 15, 236, 184, 75, 105, 248, 226, 158, 2, 49, 217, 142, 217, 202, 190, 99, 94, 95, 225, 160, 105, 206, 193, 205, 110, 73, 163, 120, 97, 175, 57, 60, 106, 75, 10, 52, 37, 100, 213, 48, 181, 60, 171, 221, 17, 129, 57, 113, 232, 192, 195, 88, 128, 17, 16, 26, 17, 210, 194, 188, 89, 240, 138, 217, 53, 115, 192, 230, 109, 228, 201, 125, 98, 20, 62, 130, 2, 169, 16, 105, 55, 121, 97, 111, 240, 70, 148, 62, 53, 245, 171, 172, 99, 208, 216, 94, 89, 87, 105, 209, 184, 75, 110, 93, 212, 95, 19, 156, 112, 78, 37, 17, 220, 36, 44, 30, 22, 158, 150, 90, 4, 237, 69, 238, 58, 238, 103, 93, 143, 195, 134, 176, 245, 76, 31, 104, 16] + static let AppleRootCA_G3_cer: [UInt8] = [48, 130, 2, 67, 48, 130, 1, 201, 160, 3, 2, 1, 2, 2, 8, 45, 197, 252, 136, 210, 197, 75, 149, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 30, 23, 13, 49, 52, 48, 52, 51, 48, 49, 56, 49, 57, 48, 54, 90, 23, 13, 51, 57, 48, 52, 51, 48, 49, 56, 49, 57, 48, 54, 90, 48, 103, 49, 27, 48, 25, 6, 3, 85, 4, 3, 12, 18, 65, 112, 112, 108, 101, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 49, 38, 48, 36, 6, 3, 85, 4, 11, 12, 29, 65, 112, 112, 108, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 49, 19, 48, 17, 6, 3, 85, 4, 10, 12, 10, 65, 112, 112, 108, 101, 32, 73, 110, 99, 46, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 48, 118, 48, 16, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 5, 43, 129, 4, 0, 34, 3, 98, 0, 4, 152, 233, 47, 61, 64, 114, 164, 237, 147, 34, 114, 129, 19, 28, 221, 16, 149, 241, 197, 163, 78, 113, 220, 20, 22, 217, 14, 229, 166, 5, 42, 119, 100, 123, 95, 78, 56, 211, 187, 28, 68, 181, 127, 245, 31, 182, 50, 98, 93, 201, 233, 132, 91, 79, 48, 79, 17, 90, 0, 253, 88, 88, 12, 165, 245, 15, 44, 77, 7, 71, 19, 117, 218, 151, 151, 151, 111, 49, 92, 237, 43, 157, 123, 32, 59, 216, 185, 84, 217, 94, 153, 164, 58, 81, 10, 49, 163, 66, 48, 64, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 187, 176, 222, 161, 88, 51, 136, 154, 164, 138, 153, 222, 190, 189, 235, 175, 218, 203, 36, 171, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1, 1, 255, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 3, 3, 104, 0, 48, 101, 2, 49, 0, 131, 233, 193, 196, 22, 94, 26, 93, 52, 24, 217, 237, 239, 244, 108, 14, 0, 70, 75, 184, 223, 178, 70, 17, 197, 15, 253, 230, 122, 140, 161, 166, 107, 206, 194, 3, 212, 156, 245, 147, 198, 116, 184, 106, 223, 170, 35, 21, 2, 48, 109, 102, 138, 16, 202, 212, 13, 212, 79, 205, 141, 67, 62, 180, 138, 99, 165, 51, 110, 227, 109, 218, 23, 183, 100, 31, 200, 83, 38, 249, 136, 98, 116, 57, 11, 23, 91, 203, 81, 168, 12, 232, 24, 3, 231, 162, 178, 40] +} diff --git a/Sources/Workspace/PackageContainer/FileSystemPackageContainer.swift b/Sources/Workspace/PackageContainer/FileSystemPackageContainer.swift index 2517c3d7f9c..444bbb1b6db 100644 --- a/Sources/Workspace/PackageContainer/FileSystemPackageContainer.swift +++ b/Sources/Workspace/PackageContainer/FileSystemPackageContainer.swift @@ -64,7 +64,8 @@ public struct FileSystemPackageContainer: PackageContainer { self.fileSystem = fileSystem self.observabilityScope = observabilityScope.makeChildScope( description: "FileSystemPackageContainer", - metadata: package.diagnosticsMetadata) + metadata: package.diagnosticsMetadata + ) } private func loadManifest() async throws -> Manifest { @@ -130,7 +131,7 @@ public struct FileSystemPackageContainer: PackageContainer { } } -extension FileSystemPackageContainer: CustomStringConvertible { +extension FileSystemPackageContainer: CustomStringConvertible { public var description: String { return "FileSystemPackageContainer(\(self.package.identity))" } diff --git a/Sources/Workspace/PackageContainer/RegistryPackageContainer.swift b/Sources/Workspace/PackageContainer/RegistryPackageContainer.swift index 1279e0d7074..f51ae3d2e88 100644 --- a/Sources/Workspace/PackageContainer/RegistryPackageContainer.swift +++ b/Sources/Workspace/PackageContainer/RegistryPackageContainer.swift @@ -54,7 +54,8 @@ public class RegistryPackageContainer: PackageContainer { self.currentToolsVersion = currentToolsVersion self.observabilityScope = observabilityScope.makeChildScope( description: "RegistryPackageContainer", - metadata: package.diagnosticsMetadata) + metadata: package.diagnosticsMetadata + ) } // MARK: - PackageContainer @@ -164,17 +165,19 @@ public class RegistryPackageContainer: PackageContainer { observabilityScope: self.observabilityScope ) // find the fake manifest so we can replace it with the real manifest content - guard let placeholderManifestFileName = try fileSystem.getDirectoryContents(.root).first(where: { file in - if file == Manifest.basename + "@swift-\(preferredToolsVersion).swift" { - return true - } else if preferredToolsVersion.patch == 0, file == Manifest.basename + "@swift-\(preferredToolsVersion.major).\(preferredToolsVersion.minor).swift" { - return true - } else if preferredToolsVersion.patch == 0, preferredToolsVersion.minor == 0, file == Manifest.basename + "@swift-\(preferredToolsVersion.major).swift" { - return true - } else { - return false - } - }) else { + guard + let placeholderManifestFileName = try fileSystem.getDirectoryContents(.root).first(where: { file in + if file == Manifest.basename + "@swift-\(preferredToolsVersion).swift" { + return true + } else if preferredToolsVersion.patch == 0, file == Manifest.basename + "@swift-\(preferredToolsVersion.major).\(preferredToolsVersion.minor).swift" { + return true + } else if preferredToolsVersion.patch == 0, preferredToolsVersion.minor == 0, file == Manifest.basename + "@swift-\(preferredToolsVersion.major).swift" { + return true + } else { + return false + } + }) + else { throw StringError("failed locating placeholder manifest for \(preferredToolsVersion)") } // replace the fake manifest with the real manifest content diff --git a/Sources/Workspace/PackageContainer/SourceControlPackageContainer.swift b/Sources/Workspace/PackageContainer/SourceControlPackageContainer.swift index 227a9d8ac4f..933cf7cd7a5 100644 --- a/Sources/Workspace/PackageContainer/SourceControlPackageContainer.swift +++ b/Sources/Workspace/PackageContainer/SourceControlPackageContainer.swift @@ -100,7 +100,8 @@ internal final class SourceControlPackageContainer: PackageContainer, CustomStri self.fingerprintCheckingMode = fingerprintCheckingMode self.observabilityScope = observabilityScope.makeChildScope( description: "SourceControlPackageContainer", - metadata: package.diagnosticsMetadata) + metadata: package.diagnosticsMetadata + ) } // Compute the map of known versions. diff --git a/Sources/Workspace/ResolvedFileWatcher.swift b/Sources/Workspace/ResolvedFileWatcher.swift index d8b5764d88d..c05f1789a9e 100644 --- a/Sources/Workspace/ResolvedFileWatcher.swift +++ b/Sources/Workspace/ResolvedFileWatcher.swift @@ -42,7 +42,7 @@ final class ResolvedFileWatcher { guard let self else { return } // Check if resolved file is part of the received paths. - let hasResolvedFile = paths.contains{ $0.appending(component: resolvedFile.basename) == resolvedFile } + let hasResolvedFile = paths.contains { $0.appending(component: resolvedFile.basename) == resolvedFile } guard hasResolvedFile else { return } self.valueLock.withLock { diff --git a/Sources/Workspace/Workspace+BinaryArtifacts.swift b/Sources/Workspace/Workspace+BinaryArtifacts.swift index 308c3e7d43f..70f93052f46 100644 --- a/Sources/Workspace/Workspace+BinaryArtifacts.swift +++ b/Sources/Workspace/Workspace+BinaryArtifacts.swift @@ -78,9 +78,9 @@ extension Workspace { observabilityScope: ObservabilityScope ) throws -> (local: [ManagedArtifact], remote: [RemoteArtifact]) { let packageAndManifests: [(reference: PackageReference, manifest: Manifest)] = - manifests.root.packages.values + // Root package and manifests. - manifests.dependencies - .map { manifest, managed, _, _ in (managed.packageRef, manifest) } // Dependency package and manifests. + manifests.root.packages.values // Root package and manifests. + + manifests.dependencies + .map { manifest, managed, _, _ in (managed.packageRef, manifest) } // Dependency package and manifests. var localArtifacts: [ManagedArtifact] = [] var remoteArtifacts: [RemoteArtifact] = [] @@ -96,15 +96,17 @@ extension Workspace { packageRef: packageReference, targetName: target.name, path: absolutePath, - kind: .unknown // an archive, we will extract it later + kind: .unknown // an archive, we will extract it later ) ) } else { - guard let (artifactPath, artifactKind) = try Self.deriveBinaryArtifact( - fileSystem: self.fileSystem, - path: absolutePath, - observabilityScope: observabilityScope - ) else { + guard + let (artifactPath, artifactKind) = try Self.deriveBinaryArtifact( + fileSystem: self.fileSystem, + path: absolutePath, + observabilityScope: observabilityScope + ) + else { observabilityScope.emit( BinaryArtifactsManagerError.localArtifactNotFound( artifactPath: absolutePath, @@ -156,83 +158,93 @@ extension Workspace { if !indexFiles.isEmpty { let errors = ThreadSafeArrayStore() - try await zipArtifacts.append(contentsOf: withThrowingTaskGroup( - of: RemoteArtifact?.self, - returning: [RemoteArtifact].self - ) { group in - let jsonDecoder = JSONDecoder.makeWithDefaults() - for indexFile in indexFiles { - group.addTask { - var request = HTTPClient.Request(method: .get, url: indexFile.url) - request.options.validResponseCodes = [200] - request.options.authorizationProvider = self.authorizationProvider? - .httpAuthorizationHeader(for:) - do { - let response = try await self.httpClient.execute(request) - guard let body = response.body else { - throw StringError("Body is empty") - } - // FIXME: would be nice if checksumAlgorithm.hash took Data directly - let bodyChecksum = self.checksumAlgorithm.hash(ByteString(body)) - .hexadecimalRepresentation - guard bodyChecksum == indexFile.checksum else { - throw StringError( - "checksum of downloaded artifact of binary target '\(indexFile.targetName)' (\(bodyChecksum)) does not match checksum specified by the manifest (\(indexFile.checksum))" + try await zipArtifacts.append( + contentsOf: withThrowingTaskGroup( + of: RemoteArtifact?.self, + returning: [RemoteArtifact].self + ) { group in + let jsonDecoder = JSONDecoder.makeWithDefaults() + for indexFile in indexFiles { + group.addTask { + var request = HTTPClient.Request(method: .get, url: indexFile.url) + request.options.validResponseCodes = [200] + request.options.authorizationProvider = + self.authorizationProvider? + .httpAuthorizationHeader(for:) + do { + let response = try await self.httpClient.execute(request) + guard let body = response.body else { + throw StringError("Body is empty") + } + // FIXME: would be nice if checksumAlgorithm.hash took Data directly + let bodyChecksum = self.checksumAlgorithm.hash(ByteString(body)) + .hexadecimalRepresentation + guard bodyChecksum == indexFile.checksum else { + throw StringError( + "checksum of downloaded artifact of binary target '\(indexFile.targetName)' (\(bodyChecksum)) does not match checksum specified by the manifest (\(indexFile.checksum))" + ) + } + let metadata = try jsonDecoder.decode(ArchiveIndexFile.self, from: body) + // FIXME: this filter needs to become more sophisticated + guard + let supportedArchive = metadata.archives.first(where: { + $0.fileName.lowercased().hasSuffix(".zip") + && $0.supportedTriples + .contains(self.hostToolchain.targetTriple) + }) + else { + throw StringError( + "No supported archive was found for '\(self.hostToolchain.targetTriple.tripleString)'" + ) + } + // add relevant archive + return RemoteArtifact( + packageRef: indexFile.packageRef, + targetName: indexFile.targetName, + url: indexFile.url.deletingLastPathComponent() + .appendingPathComponent(supportedArchive.fileName), + checksum: supportedArchive.checksum ) - } - let metadata = try jsonDecoder.decode(ArchiveIndexFile.self, from: body) - // FIXME: this filter needs to become more sophisticated - guard let supportedArchive = metadata.archives.first(where: { - $0.fileName.lowercased().hasSuffix(".zip") && $0.supportedTriples - .contains(self.hostToolchain.targetTriple) - }) else { - throw StringError( - "No supported archive was found for '\(self.hostToolchain.targetTriple.tripleString)'" + } catch { + errors.append(error) + observabilityScope.emit( + error: "failed retrieving '\(indexFile.url)'", + underlyingError: error ) } - // add relevant archive - return RemoteArtifact( - packageRef: indexFile.packageRef, - targetName: indexFile.targetName, - url: indexFile.url.deletingLastPathComponent() - .appendingPathComponent(supportedArchive.fileName), - checksum: supportedArchive.checksum - ) - } catch { - errors.append(error) - observabilityScope.emit( - error: "failed retrieving '\(indexFile.url)'", - underlyingError: error - ) - } - return nil + return nil + } } - } - // no reason to continue if we already ran into issues - if !errors.isEmpty { - throw Diagnostics.fatalError - } + // no reason to continue if we already ran into issues + if !errors.isEmpty { + throw Diagnostics.fatalError + } - return try await group.reduce(into: []) { - if let artifact = $1 { - $0.append(artifact) + return try await group.reduce(into: []) { + if let artifact = $1 { + $0.append(artifact) + } } } - }) + ) } let result = await withTaskGroup(of: ManagedArtifact?.self, returning: [ManagedArtifact].self) { group in // finally download zip files, if any for artifact in zipArtifacts { group.addTask { () -> ManagedArtifact? in - let destinationDirectory = artifactsDirectory + let destinationDirectory = + artifactsDirectory .appending(components: [artifact.packageRef.identity.description, artifact.targetName]) - guard observabilityScope.trap({ try fileSystem.createDirectory( - destinationDirectory, - recursive: true - ) }) + guard + observabilityScope.trap({ + try fileSystem.createDirectory( + destinationDirectory, + recursive: true + ) + }) else { return nil } @@ -265,38 +277,46 @@ extension Workspace { let valid = try await self.archiver.validate(path: archivePath) guard valid else { - observabilityScope.emit(BinaryArtifactsManagerError.artifactInvalidArchive( - artifactURL: artifact.url, - targetName: artifact.targetName - )) + observabilityScope.emit( + BinaryArtifactsManagerError.artifactInvalidArchive( + artifactURL: artifact.url, + targetName: artifact.targetName + ) + ) return nil } - guard let archiveChecksum = observabilityScope - .trap({ try self.checksum(forBinaryArtifactAt: archivePath) }) + guard + let archiveChecksum = + observabilityScope + .trap({ try self.checksum(forBinaryArtifactAt: archivePath) }) else { return nil } guard archiveChecksum == artifact.checksum else { - observabilityScope.emit(BinaryArtifactsManagerError.artifactInvalidChecksum( - targetName: artifact.targetName, - expectedChecksum: artifact.checksum, - actualChecksum: archiveChecksum - )) + observabilityScope.emit( + BinaryArtifactsManagerError.artifactInvalidChecksum( + targetName: artifact.targetName, + expectedChecksum: artifact.checksum, + actualChecksum: archiveChecksum + ) + ) observabilityScope.trap { try self.fileSystem.removeFileTree(archivePath) } return nil } - guard let tempExtractionDirectory = observabilityScope.trap({ () -> AbsolutePath in - let path = artifactsDirectory.appending( - components: "extract", - artifact.packageRef.identity.description, - artifact.targetName, - UUID().uuidString - ) - try self.fileSystem.forceCreateDirectory(at: path) - return path - }) else { + guard + let tempExtractionDirectory = observabilityScope.trap({ () -> AbsolutePath in + let path = artifactsDirectory.appending( + components: "extract", + artifact.packageRef.identity.description, + artifact.targetName, + UUID().uuidString + ) + try self.fileSystem.forceCreateDirectory(at: path) + return path + }) + else { return nil } @@ -336,9 +356,11 @@ extension Workspace { .getDirectoryContents(tempExtractionDirectory) // copy from temp location to actual location for file in content { - let source = tempExtractionDirectory + let source = + tempExtractionDirectory .appending(component: file) - let destination = destinationDirectory + let destination = + destinationDirectory .appending(component: file) if self.fileSystem.exists(destination) { try self.fileSystem.removeFileTree(destination) @@ -351,15 +373,19 @@ extension Workspace { } // derive concrete artifact path and type - guard let (artifactPath, artifactKind) = try? Self.deriveBinaryArtifact( - fileSystem: self.fileSystem, - path: destinationDirectory, - observabilityScope: observabilityScope - ) else { - observabilityScope.emit(BinaryArtifactsManagerError.remoteArtifactNotFound( - artifactURL: artifact.url, - targetName: artifact.targetName - )) + guard + let (artifactPath, artifactKind) = try? Self.deriveBinaryArtifact( + fileSystem: self.fileSystem, + path: destinationDirectory, + observabilityScope: observabilityScope + ) + else { + observabilityScope.emit( + BinaryArtifactsManagerError.remoteArtifactNotFound( + artifactURL: artifact.url, + targetName: artifact.targetName + ) + ) return nil } @@ -379,11 +405,13 @@ extension Workspace { ) } catch { - observabilityScope.emit(BinaryArtifactsManagerError.remoteArtifactFailedExtraction( - artifactURL: artifact.url, - targetName: artifact.targetName, - reason: error.interpolationDescription - )) + observabilityScope.emit( + BinaryArtifactsManagerError.remoteArtifactFailedExtraction( + artifactURL: artifact.url, + targetName: artifact.targetName, + reason: error.interpolationDescription + ) + ) self.delegate?.didDownloadBinaryArtifact( from: artifact.url.absoluteString, result: .failure(error), @@ -391,11 +419,13 @@ extension Workspace { ) } } catch { - observabilityScope.emit(BinaryArtifactsManagerError.artifactFailedValidation( - artifactURL: artifact.url, - targetName: artifact.targetName, - reason: error.interpolationDescription - )) + observabilityScope.emit( + BinaryArtifactsManagerError.artifactFailedValidation( + artifactURL: artifact.url, + targetName: artifact.targetName, + reason: error.interpolationDescription + ) + ) self.delegate?.didDownloadBinaryArtifact( from: artifact.url.absoluteString, result: .failure(error), @@ -404,11 +434,13 @@ extension Workspace { } } catch { observabilityScope.trap { try self.fileSystem.removeFileTree(archivePath) } - observabilityScope.emit(BinaryArtifactsManagerError.artifactFailedDownload( - artifactURL: artifact.url, - targetName: artifact.targetName, - reason: error.interpolationDescription - )) + observabilityScope.emit( + BinaryArtifactsManagerError.artifactFailedDownload( + artifactURL: artifact.url, + targetName: artifact.targetName, + reason: error.interpolationDescription + ) + ) self.delegate?.didDownloadBinaryArtifact( from: artifact.url.absoluteString, result: .failure(error), @@ -442,7 +474,8 @@ extension Workspace { try await withThrowingTaskGroup(of: ManagedArtifact?.self) { group in for artifact in artifacts { group.addTask { () -> ManagedArtifact? in - let destinationDirectory = artifactsDirectory + let destinationDirectory = + artifactsDirectory .appending(components: [artifact.packageRef.identity.description, artifact.targetName]) try fileSystem.createDirectory(destinationDirectory, recursive: true) @@ -490,11 +523,13 @@ extension Workspace { try self.fileSystem.removeFileTree(tempExtractionDirectory) // derive concrete artifact path and type - guard let (artifactPath, artifactKind) = try Self.deriveBinaryArtifact( - fileSystem: self.fileSystem, - path: destinationDirectory, - observabilityScope: observabilityScope - ) else { + guard + let (artifactPath, artifactKind) = try Self.deriveBinaryArtifact( + fileSystem: self.fileSystem, + path: destinationDirectory, + observabilityScope: observabilityScope + ) + else { throw BinaryArtifactsManagerError.localArchivedArtifactNotFound( archivePath: artifact.path, targetName: artifact.targetName @@ -515,11 +550,13 @@ extension Workspace { } catch { let reason = (error as? LocalizedError)?.errorDescription ?? error.localizedDescription - observabilityScope.emit(BinaryArtifactsManagerError.localArtifactFailedExtraction( - artifactPath: artifact.path, - targetName: artifact.targetName, - reason: reason - )) + observabilityScope.emit( + BinaryArtifactsManagerError.localArtifactFailedExtraction( + artifactPath: artifact.path, + targetName: artifact.targetName, + reason: reason + ) + ) return nil } @@ -606,7 +643,7 @@ extension Workspace { // copy from cache to destination try self.fileSystem.copy(from: cachedArtifactPath, to: destination) - return true // fetched from cache + return true // fetched from cache } // download to the cache @@ -623,7 +660,7 @@ extension Workspace { progress: progress ) try self.fileSystem.copy(from: cachedArtifactPath, to: destination) - return false // not fetched from cache + return false // not fetched from cache } catch { try? self.fileSystem.removeFileTree(cachedArtifactPath) throw error @@ -844,9 +881,9 @@ extension Workspace { for artifact in await state.artifacts { if !manifestArtifacts.local - .contains(where: { $0.packageRef == artifact.packageRef && $0.targetName == artifact.targetName }) && - !manifestArtifacts.remote .contains(where: { $0.packageRef == artifact.packageRef && $0.targetName == artifact.targetName }) + && !manifestArtifacts.remote + .contains(where: { $0.packageRef == artifact.packageRef && $0.targetName == artifact.targetName }) { artifactsToRemove.append(artifact) } @@ -862,22 +899,26 @@ extension Workspace { // If we already have an artifact that was extracted from an archive with the same checksum, // we don't need to extract the artifact again. if case .local(let existingChecksum) = existingArtifact?.source, - try existingChecksum == (self.binaryArtifactsManager.checksum(forBinaryArtifactAt: artifact.path)) + try existingChecksum == (self.binaryArtifactsManager.checksum(forBinaryArtifactAt: artifact.path)) { continue } artifactsToExtract.append(artifact) } else { - guard let _ = try BinaryArtifactsManager.deriveBinaryArtifact( - fileSystem: self.fileSystem, - path: artifact.path, - observabilityScope: observabilityScope - ) else { - observabilityScope.emit(BinaryArtifactsManagerError.localArtifactNotFound( - artifactPath: artifact.path, - targetName: artifact.targetName - )) + guard + let _ = try BinaryArtifactsManager.deriveBinaryArtifact( + fileSystem: self.fileSystem, + path: artifact.path, + observabilityScope: observabilityScope + ) + else { + observabilityScope.emit( + BinaryArtifactsManagerError.localArtifactNotFound( + artifactPath: artifact.path, + targetName: artifact.targetName + ) + ) continue } artifactsToAdd.append(artifact) diff --git a/Sources/Workspace/Workspace+Configuration.swift b/Sources/Workspace/Workspace+Configuration.swift index 9fecb0a0888..6c8a696d396 100644 --- a/Sources/Workspace/Workspace+Configuration.swift +++ b/Sources/Workspace/Workspace+Configuration.swift @@ -156,7 +156,7 @@ extension Workspace { /// Path to the shared prebuilts cache public var sharedPrebuiltsCacheDirectory: AbsolutePath? { - self.sharedCacheDirectory.map { $0.appending("prebuilts")} + self.sharedCacheDirectory.map { $0.appending("prebuilts") } } /// Create a new workspace location. @@ -292,9 +292,9 @@ extension Workspace.Configuration { public static var `default`: Self { #if canImport(Security) - Self(netrc: .user, keychain: .enabled) + Self(netrc: .user, keychain: .enabled) #else - Self(netrc: .user, keychain: .disabled) + Self(netrc: .user, keychain: .disabled) #endif } @@ -335,19 +335,21 @@ extension Workspace.Configuration { switch self.keychain { case .enabled: #if canImport(Security) - providers.append(KeychainAuthorizationProvider(observabilityScope: observabilityScope)) + providers.append(KeychainAuthorizationProvider(observabilityScope: observabilityScope)) #else - throw InternalError("Keychain not supported on this platform") + throw InternalError("Keychain not supported on this platform") #endif case .disabled: // noop break } - return providers.isEmpty ? .none : CompositeAuthorizationProvider( - providers, - observabilityScope: observabilityScope - ) + return providers.isEmpty + ? .none + : CompositeAuthorizationProvider( + providers, + observabilityScope: observabilityScope + ) } public func makeRegistryAuthorizationProvider( @@ -360,9 +362,9 @@ extension Workspace.Configuration { switch self.keychain { case .enabled: #if canImport(Security) - providers.append(KeychainAuthorizationProvider(observabilityScope: observabilityScope)) + providers.append(KeychainAuthorizationProvider(observabilityScope: observabilityScope)) #else - throw InternalError("Keychain not supported on this platform") + throw InternalError("Keychain not supported on this platform") #endif case .disabled: // noop @@ -472,7 +474,8 @@ extension Workspace.Configuration { sharedMirrorsFile: AbsolutePath? ) throws { self.localMirrors = .init(path: localMirrorsFile, fileSystem: fileSystem, deleteWhenEmpty: true) - self.sharedMirrors = sharedMirrorsFile + self.sharedMirrors = + sharedMirrorsFile .map { .init(path: $0, fileSystem: fileSystem, deleteWhenEmpty: false) } self.fileSystem = fileSystem // computes the initial mirrors diff --git a/Sources/Workspace/Workspace+Dependencies.swift b/Sources/Workspace/Workspace+Dependencies.swift index 743e6ac926e..6552bdaab0f 100644 --- a/Sources/Workspace/Workspace+Dependencies.swift +++ b/Sources/Workspace/Workspace+Dependencies.swift @@ -116,8 +116,9 @@ extension Workspace { // resolved packages for the input packages so only those packages are updated. resolvedPackages = resolvedPackagesStore.resolvedPackages .filter { - !packages.contains($0.value.packageRef.identity.description) && !packages - .contains($0.value.packageRef.deprecatedName) + !packages.contains($0.value.packageRef.identity.description) + && !packages + .contains($0.value.packageRef.deprecatedName) } } @@ -360,14 +361,15 @@ extension Workspace { // Load the `Package.resolved` store or abort now. guard let resolvedPackagesStore = observabilityScope.trap({ try self.resolvedPackagesStore.load() }), - !observabilityScope.errorsReported + !observabilityScope.errorsReported else { let dependencyManifests = try await self.loadDependencyManifests( root: graphRoot, observabilityScope: observabilityScope - ) + ) - return (dependencyManifests, + return ( + dependencyManifests, .notRequired ) } @@ -388,14 +390,14 @@ extension Workspace { return .never } else { switch resolvedPackage.state { - case .branch(_, let revision): - return .ifNeeded(revision: revision) - case .revision(let revision): - return .ifNeeded(revision: revision) - case .version(_, .some(let revision)): - return .ifNeeded(revision: revision) - case .version(_, .none): - return .always + case .branch(_, let revision): + return .ifNeeded(revision: revision) + case .revision(let revision): + return .ifNeeded(revision: revision) + case .version(_, .some(let revision)): + return .ifNeeded(revision: revision) + case .version(_, .none): + return .always } } }() @@ -465,7 +467,7 @@ extension Workspace { automaticallyAddManagedDependencies: true, observabilityScope: observabilityScope ) - + try await self.updateBinaryArtifacts( manifests: currentManifests, addedOrUpdatedPackages: [], @@ -535,11 +537,13 @@ extension Workspace { } // load and update the `Package.resolved` store with any changes from loading the top level dependencies - guard let resolvedPackagesStore = await self.loadAndUpdateResolvedPackagesStore( - dependencyManifests: currentManifests, - rootManifestsMinimumToolsVersion: rootManifestsMinimumToolsVersion, - observabilityScope: observabilityScope - ), !observabilityScope.errorsReported else { + guard + let resolvedPackagesStore = await self.loadAndUpdateResolvedPackagesStore( + dependencyManifests: currentManifests, + rootManifestsMinimumToolsVersion: rootManifestsMinimumToolsVersion, + observabilityScope: observabilityScope + ), !observabilityScope.errorsReported + else { // abort if `Package.resolved` store reported any errors. return currentManifests } @@ -597,7 +601,6 @@ extension Workspace { computedConstraints += currentManifests.editedPackagesConstraints computedConstraints += try graphRoot.constraints(self.enabledTraitsMap) + constraints - // Perform dependency resolution. let resolver = try self.createResolver(resolvedPackages: resolvedPackagesStore.resolvedPackages, observabilityScope: observabilityScope) self.activeResolver = resolver @@ -680,14 +683,16 @@ extension Workspace { observabilityScope: ObservabilityScope ) async -> [(PackageReference, PackageStateChange)] { // Get the update package states from resolved results. - guard let packageStateChanges = await observabilityScope.trap({ - try await self.computePackageStateChanges( - root: root, - resolvedDependencies: updateResults, - updateBranches: updateBranches, - observabilityScope: observabilityScope - ) - }) else { + guard + let packageStateChanges = await observabilityScope.trap({ + try await self.computePackageStateChanges( + root: root, + resolvedDependencies: updateResults, + updateBranches: updateBranches, + observabilityScope: observabilityScope + ) + }) + else { return [] } @@ -859,11 +864,9 @@ extension Workspace { observabilityScope: ObservabilityScope ) async throws -> ResolutionPrecomputationResult { let computedConstraints = - try root.constraints(self.enabledTraitsMap) + + try root.constraints(self.enabledTraitsMap) // Include constraints from the manifests in the graph root. - root.manifests.values.flatMap { try $0.dependencyConstraints(productFilter: .everything, self.enabledTraitsMap[$0.packageIdentity]) } + - dependencyManifests.dependencyConstraints + - constraints + + root.manifests.values.flatMap { try $0.dependencyConstraints(productFilter: .everything, self.enabledTraitsMap[$0.packageIdentity]) } + dependencyManifests.dependencyConstraints + constraints let precomputationProvider = ResolverPrecomputationProvider( root: root, @@ -886,11 +889,13 @@ extension Workspace { case .failure(ResolverPrecomputationError.missingPackage(let package)): return .required(reason: .newPackages(packages: [package])) case .failure(ResolverPrecomputationError.differentRequirement(let package, let state, let requirement)): - return .required(reason: .packageRequirementChange( - package: package, - state: state, - requirement: requirement - )) + return .required( + reason: .packageRequirementChange( + package: package, + state: state, + requirement: requirement + ) + ) case .failure(let error): return .required(reason: .other("\(error.interpolationDescription)")) } @@ -906,8 +911,10 @@ extension Workspace { return nil } - guard let requiredDependencies = observabilityScope - .trap({ try dependencyManifests.requiredPackages.filter(\.kind.isResolvable) }) + guard + let requiredDependencies = + observabilityScope + .trap({ try dependencyManifests.requiredPackages.filter(\.kind.isResolvable) }) else { return nil } @@ -1062,13 +1069,14 @@ extension Workspace { case .revision(let identifier, let branch): // Get the latest revision from the container. // TODO: replace with async/await when available - guard let container = try await - packageContainerProvider.getContainer( + guard + let container = try await packageContainerProvider.getContainer( for: binding.package, updateStrategy: .never, observabilityScope: observabilityScope ) - as? SourceControlPackageContainer else { + as? SourceControlPackageContainer + else { throw InternalError( "invalid container for \(binding.package) expected a SourceControlPackageContainer" ) @@ -1097,7 +1105,7 @@ extension Workspace { newState = .revision(revision) } if case .sourceControlCheckout(let checkoutState) = currentDependency.state, - checkoutState == newState + checkoutState == newState { packageStateChanges[binding.package.identity] = (binding.package, .unchanged) } else { @@ -1131,8 +1139,7 @@ extension Workspace { } // Set the state of any old package that might have been removed. for packageRef in await self.state.dependencies.lazy.map(\.packageRef) - where packageStateChanges[packageRef.identity] == nil - { + where packageStateChanges[packageRef.identity] == nil { packageStateChanges[packageRef.identity] = (packageRef, .removed) } diff --git a/Sources/Workspace/Workspace+Editing.swift b/Sources/Workspace/Workspace+Editing.swift index 62d5a7a96ef..fff97fe28b4 100644 --- a/Sources/Workspace/Workspace+Editing.swift +++ b/Sources/Workspace/Workspace+Editing.swift @@ -75,7 +75,8 @@ extension Workspace { ) guard dependency.packageRef.canonicalLocation == manifest.canonicalPackageLocation else { - return observabilityScope + return + observabilityScope .emit( error: "package at '\(destination)' is \(dependency.packageRef.identity) but was expecting \(packageIdentity)" ) @@ -83,16 +84,20 @@ extension Workspace { // Emit warnings for branch and revision, if they're present. if let checkoutBranch { - observabilityScope.emit(.editBranchNotCheckedOut( - packageName: packageIdentity, - branchName: checkoutBranch - )) + observabilityScope.emit( + .editBranchNotCheckedOut( + packageName: packageIdentity, + branchName: checkoutBranch + ) + ) } if let revision { - observabilityScope.emit(.editRevisionNotUsed( - packageName: packageIdentity, - revisionIdentifier: revision.identifier - )) + observabilityScope.emit( + .editRevisionNotUsed( + packageName: packageIdentity, + revisionIdentifier: revision.identifier + ) + ) } } else { // Otherwise, create a checkout at the destination from our repository store. @@ -169,7 +174,8 @@ extension Workspace { // If the dependency isn't in edit mode, we can't unedit it. guard case .edited(_, let unmanagedPath) = dependency.state else { - throw WorkspaceDiagnostics + throw + WorkspaceDiagnostics .DependencyNotInEditMode(dependencyName: dependency.packageRef.identity.description) } @@ -198,13 +204,13 @@ extension Workspace { } // If this was the last editable dependency, remove the editables directory too. if fileSystem.exists(self.location.editsDirectory), - try fileSystem.getDirectoryContents(self.location.editsDirectory).isEmpty + try fileSystem.getDirectoryContents(self.location.editsDirectory).isEmpty { try fileSystem.removeFileTree(self.location.editsDirectory) } if case .edited(let basedOn, _) = dependency.state, - case .sourceControlCheckout(let checkoutState) = basedOn?.state + case .sourceControlCheckout(let checkoutState) = basedOn?.state { // Restore the original checkout. // diff --git a/Sources/Workspace/Workspace+Manifests.swift b/Sources/Workspace/Workspace+Manifests.swift index 5c6093268e0..e416b5a47c6 100644 --- a/Sources/Workspace/Workspace+Manifests.swift +++ b/Sources/Workspace/Workspace+Manifests.swift @@ -57,22 +57,26 @@ extension Workspace { var root: PackageGraphRoot /// The dependency manifests in the transitive closure of root manifest. - let dependencies: [( - manifest: Manifest, - dependency: ManagedDependency, - productFilter: ProductFilter, - fileSystem: FileSystem - )] + let dependencies: + [( + manifest: Manifest, + dependency: ManagedDependency, + productFilter: ProductFilter, + fileSystem: FileSystem + )] private let workspace: Workspace private let observabilityScope: ObservabilityScope - private let _dependencies: LoadableResult<( - required: OrderedCollections.OrderedSet, - missing: OrderedCollections.OrderedSet, - unused: OrderedCollections.OrderedSet - )> + private let _dependencies: + LoadableResult< + ( + required: OrderedCollections.OrderedSet, + missing: OrderedCollections.OrderedSet, + unused: OrderedCollections.OrderedSet + ) + > private let _constraints: LoadableResult<[PackageContainerConstraint]> @@ -109,14 +113,18 @@ extension Workspace { } /// Returns all manifests contained in DependencyManifests. - public var allDependencyManifests: OrderedCollections.OrderedDictionary< - PackageIdentity, - (manifest: Manifest, fs: FileSystem) - > { - self.dependencies.reduce(into: OrderedCollections.OrderedDictionary< + public var allDependencyManifests: + OrderedCollections.OrderedDictionary< PackageIdentity, (manifest: Manifest, fs: FileSystem) - >()) { partial, item in + > + { + self.dependencies.reduce( + into: OrderedCollections.OrderedDictionary< + PackageIdentity, + (manifest: Manifest, fs: FileSystem) + >() + ) { partial, item in partial[item.dependency.packageRef.identity] = (item.manifest, item.fileSystem) } } @@ -208,32 +216,35 @@ extension Workspace { var unusedIdentities: OrderedCollections.OrderedSet = [] var inputIdentities: OrderedCollections.OrderedSet = [] - let inputNodes: [GraphLoadingNode] = try root.packages.map { identity, package in - inputIdentities.append(package.reference) + let inputNodes: [GraphLoadingNode] = + try root.packages.map { identity, package in + inputIdentities.append(package.reference) - let node = try GraphLoadingNode( - identity: identity, - manifest: package.manifest, - productFilter: .everything, - enabledTraits: workspace.enabledTraitsMap[package.reference.identity] - ) - return node - } + root.dependencies.compactMap { dependency in - let package = dependency.packageRef - inputIdentities.append(package) - return try manifestsMap[dependency.identity].map { manifest in - - return try GraphLoadingNode( - identity: dependency.identity, - manifest: manifest, - productFilter: dependency.productFilter, - enabledTraits: workspace.enabledTraitsMap[dependency.identity] + let node = try GraphLoadingNode( + identity: identity, + manifest: package.manifest, + productFilter: .everything, + enabledTraits: workspace.enabledTraitsMap[package.reference.identity] ) + return node + } + + root.dependencies.compactMap { dependency in + let package = dependency.packageRef + inputIdentities.append(package) + return try manifestsMap[dependency.identity].map { manifest in + + return try GraphLoadingNode( + identity: dependency.identity, + manifest: manifest, + productFilter: dependency.productFilter, + enabledTraits: workspace.enabledTraitsMap[dependency.identity] + ) + } } - } // Begin with all packages having everything as an unused dependency. - var unusedDepsPerPackage: [PackageIdentity: [PackageReference]] = manifestsMap + var unusedDepsPerPackage: [PackageIdentity: [PackageReference]] = + manifestsMap .reduce(into: [PackageIdentity: [PackageReference]]()) { depsMap, manifestMap in depsMap[manifestMap.key] = manifestsMap.compactMap { identity, manifest in guard !root.manifests.contains(where: { identity == $0.key }) else { return nil } @@ -259,16 +270,20 @@ extension Workspace { ) if !isDepUsed && workspace.configuration.pruneDependencies { if !node.enabledTraits.isEmpty { - observabilityScope.emit(debug: """ - '\(package.identity)' from '\(package.locationString)' was omitted \ - from required dependencies because it is being guarded by the following traits:' \ - \(node.enabledTraits.joined(separator: ", ")) - """) + observabilityScope.emit( + debug: """ + '\(package.identity)' from '\(package.locationString)' was omitted \ + from required dependencies because it is being guarded by the following traits:' \ + \(node.enabledTraits.joined(separator: ", ")) + """ + ) } else { - observabilityScope.emit(debug: """ - '\(package.identity)' from '\(package.locationString)' was omitted \ - from required dependencies because it is unused - """) + observabilityScope.emit( + debug: """ + '\(package.identity)' from '\(package.locationString)' was omitted \ + from required dependencies because it is unused + """ + ) } } else { unusedDepsPerPackage[node.identity, default: []] = unusedDepsPerPackage[ @@ -286,20 +301,24 @@ extension Workspace { if topLevelDependencies.contains(where: { $0.locationString == existing.locationString }) { - observabilityScope.emit(debug: """ - similar variants of package '\(package.identity)' \ - found at '\(package.locationString)' and '\(existing.locationString)'. \ - using preferred root variant '\(existing.locationString)' - """) + observabilityScope.emit( + debug: """ + similar variants of package '\(package.identity)' \ + found at '\(package.locationString)' and '\(existing.locationString)'. \ + using preferred root variant '\(existing.locationString)' + """ + ) } else { let preferred = [existing, package].sorted(by: { $0.locationString > $1.locationString - }).first! // safe - observabilityScope.emit(debug: """ - similar variants of package '\(package.identity)' \ - found at '\(package.locationString)' and '\(existing.locationString)'. \ - using preferred variant '\(preferred.locationString)' - """) + }).first! // safe + observabilityScope.emit( + debug: """ + similar variants of package '\(package.identity)' \ + found at '\(package.locationString)' and '\(existing.locationString)'. \ + using preferred variant '\(preferred.locationString)' + """ + ) if preferred.locationString != existing.locationString { requiredIdentities.remove(existing) requiredIdentities.insert(preferred, at: index) @@ -307,11 +326,13 @@ extension Workspace { } } } else { - observabilityScope.emit(debug: """ - '\(package.identity)' from '\(package.locationString)' was omitted \ - from required dependencies because it has the same identity as the \ - one from '\(existing.locationString)' - """) + observabilityScope.emit( + debug: """ + '\(package.identity)' from '\(package.locationString)' was omitted \ + from required dependencies because it has the same identity as the \ + one from '\(existing.locationString)' + """ + ) } } } @@ -343,20 +364,22 @@ extension Workspace { requiredIdentities = requiredIdentities.subtracting(unusedIdentities) } - var availableIdentities: Set = try Set(manifestsMap.map { - // FIXME: adding this guard to ensure refactoring is correct 9/21 - // we only care about remoteSourceControl for this validation. it would otherwise trigger for - // a dependency is put into edit mode, which we want to deprecate anyways - if case .remoteSourceControl = $0.1.packageKind { - let effectiveURL = workspace.mirrors.effective(for: $0.1.packageLocation) - guard effectiveURL == $0.1.packageKind.locationString else { - throw InternalError( - "effective url for \($0.1.packageLocation) is \(effectiveURL), different from expected \($0.1.packageKind.locationString)" - ) + var availableIdentities: Set = try Set( + manifestsMap.map { + // FIXME: adding this guard to ensure refactoring is correct 9/21 + // we only care about remoteSourceControl for this validation. it would otherwise trigger for + // a dependency is put into edit mode, which we want to deprecate anyways + if case .remoteSourceControl = $0.1.packageKind { + let effectiveURL = workspace.mirrors.effective(for: $0.1.packageLocation) + guard effectiveURL == $0.1.packageKind.locationString else { + throw InternalError( + "effective url for \($0.1.packageLocation) is \(effectiveURL), different from expected \($0.1.packageKind.locationString)" + ) + } } + return PackageReference(identity: $0.key, kind: $0.1.packageKind) } - return PackageReference(identity: $0.key, kind: $0.1.packageKind) - }) + ) if workspace.configuration.pruneDependencies { availableIdentities = availableIdentities.subtracting(unusedIdentities) @@ -474,13 +497,14 @@ extension Workspace { throw StringError("unexpected manifest loader kind") } - let manifestToolsVersion = (try? ToolsVersionParser.parse( - manifestPath: manifestPath, - fileSystem: self.fileSystem - )) ?? self.currentToolsVersion + let manifestToolsVersion = + (try? ToolsVersionParser.parse( + manifestPath: manifestPath, + fileSystem: self.fileSystem + )) ?? self.currentToolsVersion guard self.currentToolsVersion >= manifestToolsVersion || SwiftVersion.current.isDevelopment, - manifestToolsVersion >= ToolsVersion.minimumRequired + manifestToolsVersion >= ToolsVersion.minimumRequired else { throw StringError("invalid tools version") } @@ -581,9 +605,12 @@ extension Workspace { ) } - let topLevelManifests = rootManifests.merging(rootDependenciesManifests, uniquingKeysWith: { lhs, _ in - lhs // prefer roots! - }) + let topLevelManifests = rootManifests.merging( + rootDependenciesManifests, + uniquingKeysWith: { lhs, _ in + lhs // prefer roots! + } + ) // optimization: preload first level dependencies manifest (in parallel) let firstLevelDependencies = try topLevelManifests.values.map { manifest in @@ -612,44 +639,44 @@ extension Workspace { // Continue to load the rest of the manifest for this graph // Creates a map of loaded manifests. We do this to avoid reloading the shared nodes. var loadedManifests = firstLevelManifests - let successorNodes: (KeyedPair) async throws -> [KeyedPair< - GraphLoadingNode, - PackageIdentity - >] = { node in - // optimization: preload manifest we know about in parallel - // avoid loading dependencies that are trait-guarded here since this is redundant. - let dependenciesRequired = try node.item.manifest.dependenciesRequired( - for: node.item.productFilter, - node.item.enabledTraits - ) - let dependenciesToLoad = dependenciesRequired.map(\.packageRef) - .filter { !loadedManifests.keys.contains($0.identity) } - try await prepopulateManagedDependencies(dependenciesToLoad) - let dependenciesManifests = try await self.loadManagedManifests( - for: dependenciesToLoad, - observabilityScope: observabilityScope - ) - dependenciesManifests.forEach { loadedManifests[$0.key] = $0.value } - return try dependenciesRequired.compactMap { dependency in - return try loadedManifests[dependency.identity].flatMap { manifest in - // we also compare the location as this function may attempt to load - // dependencies that have the same identity but from a different location - // which is an error case we diagnose an report about in the GraphLoading part which - // is prepared to handle the case where not all manifest are available - return manifest.canonicalPackageLocation == dependency.packageRef.canonicalLocation ? - try KeyedPair( - GraphLoadingNode( - identity: dependency.identity, - manifest: manifest, - productFilter: dependency.productFilter, - enabledTraits: self.enabledTraitsMap[dependency.identity] - ), - key: dependency.identity - ) : - nil + let successorNodes: + (KeyedPair) async throws -> [KeyedPair< + GraphLoadingNode, + PackageIdentity + >] = { node in + // optimization: preload manifest we know about in parallel + // avoid loading dependencies that are trait-guarded here since this is redundant. + let dependenciesRequired = try node.item.manifest.dependenciesRequired( + for: node.item.productFilter, + node.item.enabledTraits + ) + let dependenciesToLoad = dependenciesRequired.map(\.packageRef) + .filter { !loadedManifests.keys.contains($0.identity) } + try await prepopulateManagedDependencies(dependenciesToLoad) + let dependenciesManifests = try await self.loadManagedManifests( + for: dependenciesToLoad, + observabilityScope: observabilityScope + ) + dependenciesManifests.forEach { loadedManifests[$0.key] = $0.value } + return try dependenciesRequired.compactMap { dependency in + return try loadedManifests[dependency.identity].flatMap { manifest in + // we also compare the location as this function may attempt to load + // dependencies that have the same identity but from a different location + // which is an error case we diagnose an report about in the GraphLoading part which + // is prepared to handle the case where not all manifest are available + return manifest.canonicalPackageLocation == dependency.packageRef.canonicalLocation + ? try KeyedPair( + GraphLoadingNode( + identity: dependency.identity, + manifest: manifest, + productFilter: dependency.productFilter, + enabledTraits: self.enabledTraitsMap[dependency.identity] + ), + key: dependency.identity + ) : nil + } } } - } var allNodes = OrderedDictionary() @@ -691,7 +718,7 @@ extension Workspace { let rootManifestsByName = Array(root.manifests.values).spm_createDictionary { ($0.displayName, $0) } for (_, node) in dependencyManifests { if let override = rootManifestsByName[node.manifest.displayName], - override.packageLocation != node.manifest.packageLocation + override.packageLocation != node.manifest.packageLocation { observabilityScope .emit( diff --git a/Sources/Workspace/Workspace+PackageContainer.swift b/Sources/Workspace/Workspace+PackageContainer.swift index d2fd3eda3a3..f4642af3c12 100644 --- a/Sources/Workspace/Workspace+PackageContainer.swift +++ b/Sources/Workspace/Workspace+PackageContainer.swift @@ -65,7 +65,8 @@ extension Workspace: PackageContainerProvider { manifestLoader: self.manifestLoader, currentToolsVersion: self.currentToolsVersion, fingerprintStorage: self.fingerprints, - fingerprintCheckingMode: FingerprintCheckingMode + fingerprintCheckingMode: + FingerprintCheckingMode .map(self.configuration.fingerprintCheckingMode), observabilityScope: observabilityScope ) diff --git a/Sources/Workspace/Workspace+Prebuilts.swift b/Sources/Workspace/Workspace+Prebuilts.swift index db8c3371c57..438b90dd786 100644 --- a/Sources/Workspace/Workspace+Prebuilts.swift +++ b/Sources/Workspace/Workspace+Prebuilts.swift @@ -196,11 +196,11 @@ extension Workspace { self.httpClient = customHTTPClient ?? HTTPClient() self.customSwiftCompilerVersion = customSwiftCompilerVersion -#if os(Linux) - self.archiver = customArchiver ?? TarArchiver(fileSystem: fileSystem) -#else - self.archiver = customArchiver ?? ZipArchiver(fileSystem: fileSystem) -#endif + #if os(Linux) + self.archiver = customArchiver ?? TarArchiver(fileSystem: fileSystem) + #else + self.archiver = customArchiver ?? ZipArchiver(fileSystem: fileSystem) + #endif self.scratchPath = scratchPath self.cachePath = cachePath @@ -231,7 +231,7 @@ extension Workspace { kind: .remoteSourceControl("git@github.com:swiftlang/swift-syntax.git") ), ] - ), + ) ] } @@ -253,7 +253,8 @@ extension Workspace { if let prebuilt = prebuiltPackages.first(where: { $0.packageRefs.contains(where: { guard case let .remoteSourceControl(prebuiltURL) = $0.kind, - $0.identity == packageRef.identity else { + $0.identity == packageRef.identity + else { return false } @@ -356,7 +357,9 @@ extension Workspace { try fileSystem.createDirectory(destination.parentDirectory, recursive: true) let manifestURL = self.prebuiltsDownloadURL.appending( - components: package.identity.description, version.description, manifestFile + components: package.identity.description, + version.description, + manifestFile ) if manifestURL.scheme == "file" { @@ -377,7 +380,7 @@ extension Workspace { destination: destination ) request.options.authorizationProvider = - self.authorizationProvider?.httpAuthorizationHeader(for:) + self.authorizationProvider?.httpAuthorizationHeader(for:) request.options.retryStrategy = .exponentialBackoff( maxAttempts: 3, baseDelay: .milliseconds(50) @@ -463,7 +466,9 @@ extension Workspace { // Download let artifactURL = self.prebuiltsDownloadURL.appending( - components: package.identity.description, version.description, artifactFile + components: package.identity.description, + version.description, + artifactFile ) let fetchStart = DispatchTime.now() @@ -495,7 +500,7 @@ extension Workspace { destination: destination ) request.options.authorizationProvider = - self.authorizationProvider?.httpAuthorizationHeader(for:) + self.authorizationProvider?.httpAuthorizationHeader(for:) request.options.retryStrategy = .exponentialBackoff( maxAttempts: 3, baseDelay: .milliseconds(50) @@ -605,7 +610,8 @@ extension Workspace { guard let manifest = manifests.allDependencyManifests[prebuilt.identity], let packageVersion = manifest.manifest.version, - let prebuiltManifest = try await prebuiltsManager + let prebuiltManifest = + try await prebuiltsManager .downloadManifest( workspace: self, package: prebuilt, @@ -620,7 +626,8 @@ extension Workspace { for library in prebuiltManifest.libraries { for artifact in library.artifacts ?? [] where artifact.platform == hostPlatform { - if let path = try await prebuiltsManager + if let path = + try await prebuiltsManager .downloadPrebuilt( workspace: self, package: prebuilt, @@ -700,127 +707,127 @@ extension Workspace.PrebuiltsManifest.Platform { /// Determine host platform based on compilation target public static var hostPlatform: Self? { let arch: Arch? -#if arch(arm64) - arch = .aarch64 -#elseif arch(x86_64) - arch = .x86_64 -#else - arch = nil -#endif + #if arch(arm64) + arch = .aarch64 + #elseif arch(x86_64) + arch = .x86_64 + #else + arch = nil + #endif guard let arch else { return nil } -#if os(macOS) - switch arch { - case .aarch64: - return .macos_aarch64 - case .x86_64: - return .macos_x86_64 - } -#elseif os(Windows) - switch arch { - case .aarch64: - return .windows_aarch64 - case .x86_64: - return .windows_x86_64 - } -#elseif os(Linux) - // Load up the os-release file into a dictionary - guard let osData = try? String(contentsOfFile: "/etc/os-release", encoding: .utf8) - else { - return nil - } - let osLines = osData.split(separator: "\n") - let osDict = osLines.reduce(into: [Substring: String]()) { - (dict, line) in - let parts = line.split(separator: "=", maxSplits: 2) - dict[parts[0]] = parts[1...].joined(separator: "=").trimmingCharacters(in: ["\""]) - } - - switch osDict["ID"] { - case "ubuntu": - switch osDict["VERSION_CODENAME"] { - case "noble": - switch arch { - case .aarch64: - return .ubuntu_noble_aarch64 - case .x86_64: - return .ubuntu_noble_x86_64 - } - case "jammy": - switch arch { - case .aarch64: - return .ubuntu_jammy_aarch64 - case .x86_64: - return .ubuntu_jammy_x86_64 - } - case "focal": - switch arch { - case .aarch64: - return .ubuntu_focal_aarch64 - case .x86_64: - return .ubuntu_focal_x86_64 - } - default: - return nil + #if os(macOS) + switch arch { + case .aarch64: + return .macos_aarch64 + case .x86_64: + return .macos_x86_64 } - case "fedora": - switch osDict["VERSION_ID"] { - case "39", "41": - switch arch { - case .aarch64: - return .fedora_39_aarch64 - case .x86_64: - return .fedora_39_x86_64 - } - default: - return nil + #elseif os(Windows) + switch arch { + case .aarch64: + return .windows_aarch64 + case .x86_64: + return .windows_x86_64 } - case "amzn": - switch osDict["VERSION_ID"] { - case "2": - switch arch { - case .aarch64: - return .amazonlinux2_aarch64 - case .x86_64: - return .amazonlinux2_x86_64 - } - default: + #elseif os(Linux) + // Load up the os-release file into a dictionary + guard let osData = try? String(contentsOfFile: "/etc/os-release", encoding: .utf8) + else { return nil } - case "rhel": - guard let version = osDict["VERSION_ID"] else { - return nil + let osLines = osData.split(separator: "\n") + let osDict = osLines.reduce(into: [Substring: String]()) { + (dict, line) in + let parts = line.split(separator: "=", maxSplits: 2) + dict[parts[0]] = parts[1...].joined(separator: "=").trimmingCharacters(in: ["\""]) } - switch version.split(separator: ".")[0] { - case "9": - switch arch { - case .aarch64: - return .rhel_ubi9_aarch64 - case .x86_64: - return .rhel_ubi9_x86_64 + + switch osDict["ID"] { + case "ubuntu": + switch osDict["VERSION_CODENAME"] { + case "noble": + switch arch { + case .aarch64: + return .ubuntu_noble_aarch64 + case .x86_64: + return .ubuntu_noble_x86_64 + } + case "jammy": + switch arch { + case .aarch64: + return .ubuntu_jammy_aarch64 + case .x86_64: + return .ubuntu_jammy_x86_64 + } + case "focal": + switch arch { + case .aarch64: + return .ubuntu_focal_aarch64 + case .x86_64: + return .ubuntu_focal_x86_64 + } + default: + return nil } - default: - return nil - } - case "debian": - switch osDict["VERSION_ID"] { - case "12": - switch arch { - case .aarch64: - return .debian_12_aarch64 - case .x86_64: - return .debian_12_x86_64 + case "fedora": + switch osDict["VERSION_ID"] { + case "39", "41": + switch arch { + case .aarch64: + return .fedora_39_aarch64 + case .x86_64: + return .fedora_39_x86_64 + } + default: + return nil + } + case "amzn": + switch osDict["VERSION_ID"] { + case "2": + switch arch { + case .aarch64: + return .amazonlinux2_aarch64 + case .x86_64: + return .amazonlinux2_x86_64 + } + default: + return nil + } + case "rhel": + guard let version = osDict["VERSION_ID"] else { + return nil + } + switch version.split(separator: ".")[0] { + case "9": + switch arch { + case .aarch64: + return .rhel_ubi9_aarch64 + case .x86_64: + return .rhel_ubi9_x86_64 + } + default: + return nil + } + case "debian": + switch osDict["VERSION_ID"] { + case "12": + switch arch { + case .aarch64: + return .debian_12_aarch64 + case .x86_64: + return .debian_12_x86_64 + } + default: + return nil } default: return nil } - default: + #else return nil - } -#else - return nil -#endif + #endif } } diff --git a/Sources/Workspace/Workspace+Registry.swift b/Sources/Workspace/Workspace+Registry.swift index c9b3feebed1..5974409b1ba 100644 --- a/Sources/Workspace/Workspace+Registry.swift +++ b/Sources/Workspace/Workspace+Registry.swift @@ -57,7 +57,7 @@ extension Workspace { private let registryClient: RegistryClient private let transformationMode: TransformationMode - private let cacheTTL = DispatchTimeInterval.seconds(300) // 5m + private let cacheTTL = DispatchTimeInterval.seconds(300) // 5m private let identityLookupCache = ThreadSafeKeyValueStore< SourceControlURL, (result: Result, expirationTime: DispatchTime) @@ -205,8 +205,10 @@ extension Workspace { .emit( info: "swizzling '\(dependency.locationString)' with registry dependency '\(registryIdentity)'." ) - targetDependencyPackageNameTransformations[dependency - .nameForModuleDependencyResolutionOnly.lowercased()] = registryIdentity.description + targetDependencyPackageNameTransformations[ + dependency + .nameForModuleDependencyResolutionOnly.lowercased() + ] = registryIdentity.description modifiedDependency = .registry( identity: registryIdentity, requirement: requirement, @@ -251,9 +253,9 @@ extension Workspace { condition: let condition ): if let packageName, - // makes sure we use the updated package name for target based dependencies - let modifiedPackageName = - targetDependencyPackageNameTransformations[packageName.lowercased()] + // makes sure we use the updated package name for target based dependencies + let modifiedPackageName = + targetDependencyPackageNameTransformations[packageName.lowercased()] { modifiedDependency = .product( name: name, diff --git a/Sources/Workspace/Workspace+SourceControl.swift b/Sources/Workspace/Workspace+SourceControl.swift index 8c8c63f6fe3..087fd562255 100644 --- a/Sources/Workspace/Workspace+SourceControl.swift +++ b/Sources/Workspace/Workspace+SourceControl.swift @@ -104,7 +104,7 @@ extension Workspace { case .version(let version, revision: let revision) where revision != nil: return try await self.checkoutRepository( package: package, - at: .version(version, revision: .init(identifier: revision!)), // nil checked above + at: .version(version, revision: .init(identifier: revision!)), // nil checked above observabilityScope: observabilityScope ) case .branch(let branch, revision: let revision): diff --git a/Sources/Workspace/Workspace+State.swift b/Sources/Workspace/Workspace+State.swift index cd8c9a6eeab..1f49bbb6249 100644 --- a/Sources/Workspace/Workspace+State.swift +++ b/Sources/Workspace/Workspace+State.swift @@ -89,7 +89,7 @@ public actor WorkspaceState { self.artifacts = storedState.artifacts self.prebuilts = storedState.prebuilts } - + public func add(dependency: Workspace.ManagedDependency) { dependencies = dependencies.add(dependency) } @@ -293,21 +293,26 @@ extension WorkspaceStateStorage { return try self.init(underlying: .sourceControlCheckout(.init(checkout))) case "registryDownload": let version = try container.decode(String.self, forKey: .version) - return try self + return + try self .init(underlying: .registryDownload(version: TSCUtility.Version(versionString: version))) case "edited": let path = try container.decode(Basics.AbsolutePath?.self, forKey: .path) - return try self.init(underlying: .edited( - basedOn: basedOn.map { try .init($0) }, - unmanagedPath: path - )) + return try self.init( + underlying: .edited( + basedOn: basedOn.map { try .init($0) }, + unmanagedPath: path + ) + ) case "custom": let version = try container.decode(String.self, forKey: .version) let path = try container.decode(Basics.AbsolutePath.self, forKey: .path) - return try self.init(underlying: .custom( - version: TSCUtility.Version(versionString: version), - path: path - )) + return try self.init( + underlying: .custom( + version: TSCUtility.Version(versionString: version), + path: path + ) + ) default: throw StringError("unknown dependency state \(kind)") } @@ -691,21 +696,26 @@ extension WorkspaceStateStorage { return try self.init(underlying: .sourceControlCheckout(.init(checkout))) case "registryDownload": let version = try container.decode(String.self, forKey: .version) - return try self + return + try self .init(underlying: .registryDownload(version: TSCUtility.Version(versionString: version))) case "edited": let path = try container.decode(Basics.AbsolutePath?.self, forKey: .path) - return try self.init(underlying: .edited( - basedOn: basedOn.map { try .init($0) }, - unmanagedPath: path - )) + return try self.init( + underlying: .edited( + basedOn: basedOn.map { try .init($0) }, + unmanagedPath: path + ) + ) case "custom": let version = try container.decode(String.self, forKey: .version) let path = try container.decode(Basics.AbsolutePath.self, forKey: .path) - return try self.init(underlying: .custom( - version: TSCUtility.Version(versionString: version), - path: path - )) + return try self.init( + underlying: .custom( + version: TSCUtility.Version(versionString: version), + path: path + ) + ) default: throw StringError("unknown dependency state \(kind)") } @@ -1047,21 +1057,26 @@ extension WorkspaceStateStorage { return try self.init(underlying: .sourceControlCheckout(.init(checkout))) case "registryDownload": let version = try container.decode(String.self, forKey: .version) - return try self + return + try self .init(underlying: .registryDownload(version: TSCUtility.Version(versionString: version))) case "edited": let path = try container.decode(Basics.AbsolutePath?.self, forKey: .path) - return try self.init(underlying: .edited( - basedOn: basedOn.map { try .init($0) }, - unmanagedPath: path - )) + return try self.init( + underlying: .edited( + basedOn: basedOn.map { try .init($0) }, + unmanagedPath: path + ) + ) case "custom": let version = try container.decode(String.self, forKey: .version) let path = try container.decode(Basics.AbsolutePath.self, forKey: .path) - return try self.init(underlying: .custom( - version: TSCUtility.Version(versionString: version), - path: path - )) + return try self.init( + underlying: .custom( + version: TSCUtility.Version(versionString: version), + path: path + ) + ) default: throw StringError("unknown dependency state \(kind)") } @@ -1353,10 +1368,12 @@ extension WorkspaceStateStorage { return try self.init(underlying: .sourceControlCheckout(.init(checkout))) case "edited": let path = try container.decode(Basics.AbsolutePath?.self, forKey: .path) - return try self.init(underlying: .edited( - basedOn: basedOn.map { try .init($0) }, - unmanagedPath: path - )) + return try self.init( + underlying: .edited( + basedOn: basedOn.map { try .init($0) }, + unmanagedPath: path + ) + ) default: throw StringError("unknown dependency state \(kind)") } diff --git a/Sources/Workspace/Workspace+Traits.swift b/Sources/Workspace/Workspace+Traits.swift index 856627f4fcb..261c0076788 100644 --- a/Sources/Workspace/Workspace+Traits.swift +++ b/Sources/Workspace/Workspace+Traits.swift @@ -29,16 +29,15 @@ extension Workspace { // the trait configuration set in the `Workspace`. Otherwise, // check the enabled traits map to see if there are traits // that have already been recorded as enabled. - let explicitlyEnabledTraits = manifest.packageKind.isRoot ? - try manifest.enabledTraits(using: self.traitConfiguration) : - self.enabledTraitsMap[manifest.packageIdentity] + let explicitlyEnabledTraits = manifest.packageKind.isRoot ? try manifest.enabledTraits(using: self.traitConfiguration) : self.enabledTraitsMap[manifest.packageIdentity] var enabledTraits = try manifest.enabledTraits(using: explicitlyEnabledTraits) // Check if any parents requested default traits for this package // If so, expand the default traits and union them with existing traits if let defaultSetters = self.enabledTraitsMap[defaultSettersFor: manifest.packageIdentity], - !defaultSetters.isEmpty { + !defaultSetters.isEmpty + { // Calculate what the default traits are for this manifest let defaultTraits = try manifest.enabledTraits(using: .defaults) @@ -70,7 +69,8 @@ extension Workspace { if let dependencyTraits = dependency.traits { // Parent explicitly specified traits (could be [] to disable, or a list of specific traits) - let explicitlyEnabledTraits = dependencyTraits + let explicitlyEnabledTraits = + dependencyTraits .filter { $0.isEnabled(by: parentEnabledTraits) } .map(\.name) diff --git a/Sources/Workspace/Workspace.swift b/Sources/Workspace/Workspace.swift index 76054b6988d..2b950e6fb88 100644 --- a/Sources/Workspace/Workspace.swift +++ b/Sources/Workspace/Workspace.swift @@ -459,19 +459,23 @@ public class Workspace { ) let currentToolsVersion = customToolsVersion ?? ToolsVersion.current - let hostToolchain = try customHostToolchain ?? UserToolchain( - swiftSDK: .hostSwiftSDK( - environment: environment - ), - environment: environment, - fileSystem: fileSystem - ) - var manifestLoader = customManifestLoader ?? ManifestLoader( - toolchain: hostToolchain, - cacheDir: location.sharedManifestsCacheDirectory, - importRestrictions: configuration?.manifestImportRestrictions, - pruneDependencies: configuration?.pruneDependencies ?? false - ) + let hostToolchain = + try customHostToolchain + ?? UserToolchain( + swiftSDK: .hostSwiftSDK( + environment: environment + ), + environment: environment, + fileSystem: fileSystem + ) + var manifestLoader = + customManifestLoader + ?? ManifestLoader( + toolchain: hostToolchain, + cacheDir: location.sharedManifestsCacheDirectory, + importRestrictions: configuration?.manifestImportRestrictions, + pruneDependencies: configuration?.pruneDependencies ?? false + ) // set delegate if not set if let manifestLoader = manifestLoader as? ManifestLoader, manifestLoader.delegate == nil { manifestLoader.delegate = delegate.map(WorkspaceManifestLoaderDelegate.init(workspaceDelegate:)) @@ -479,62 +483,76 @@ public class Workspace { let configuration = configuration ?? .default - let mirrors = try customMirrors ?? Workspace.Configuration.Mirrors( - fileSystem: fileSystem, - localMirrorsFile: location.localMirrorsConfigurationFile, - sharedMirrorsFile: location.sharedMirrorsConfigurationFile - ).mirrors - - let identityResolver = customIdentityResolver ?? DefaultIdentityResolver( - locationMapper: mirrors.effective(for:), - identityMapper: mirrors.effectiveIdentity(for:) - ) + let mirrors = + try customMirrors + ?? Workspace.Configuration.Mirrors( + fileSystem: fileSystem, + localMirrorsFile: location.localMirrorsConfigurationFile, + sharedMirrorsFile: location.sharedMirrorsConfigurationFile + ).mirrors + + let identityResolver = + customIdentityResolver + ?? DefaultIdentityResolver( + locationMapper: mirrors.effective(for:), + identityMapper: mirrors.effectiveIdentity(for:) + ) let dependencyMapper = customDependencyMapper ?? DefaultDependencyMapper(identityResolver: identityResolver) let checksumAlgorithm = customChecksumAlgorithm ?? SHA256() let repositoryProvider = customRepositoryProvider ?? GitRepositoryProvider() - let repositoryManager = customRepositoryManager ?? RepositoryManager( - fileSystem: fileSystem, - path: location.repositoriesDirectory, - provider: repositoryProvider, - cachePath: configuration.sharedDependenciesCacheEnabled ? location.sharedRepositoriesCacheDirectory : .none, - initializationWarningHandler: initializationWarningHandler, - delegate: delegate.map(WorkspaceRepositoryManagerDelegate.init(workspaceDelegate:)) - ) + let repositoryManager = + customRepositoryManager + ?? RepositoryManager( + fileSystem: fileSystem, + path: location.repositoriesDirectory, + provider: repositoryProvider, + cachePath: configuration.sharedDependenciesCacheEnabled ? location.sharedRepositoriesCacheDirectory : .none, + initializationWarningHandler: initializationWarningHandler, + delegate: delegate.map(WorkspaceRepositoryManagerDelegate.init(workspaceDelegate:)) + ) // register the source control dependencies fetcher with the cancellation handler cancellator?.register(name: "repository fetching", handler: repositoryManager) - let fingerprints = customFingerprints ?? location.sharedFingerprintsDirectory.map { - FilePackageFingerprintStorage( - fileSystem: fileSystem, - directoryPath: $0 - ) - } + let fingerprints = + customFingerprints + ?? location.sharedFingerprintsDirectory.map { + FilePackageFingerprintStorage( + fileSystem: fileSystem, + directoryPath: $0 + ) + } - let signingEntities = customSigningEntities ?? location.sharedSigningEntitiesDirectory.map { - FilePackageSigningEntityStorage( + let signingEntities = + customSigningEntities + ?? location.sharedSigningEntitiesDirectory.map { + FilePackageSigningEntityStorage( + fileSystem: fileSystem, + directoryPath: $0 + ) + } + + let registriesConfiguration = + try customRegistriesConfiguration + ?? Workspace.Configuration.Registries( fileSystem: fileSystem, - directoryPath: $0 + localRegistriesFile: location.localRegistriesConfigurationFile, + sharedRegistriesFile: location.sharedRegistriesConfigurationFile + ).configuration + + let registryClient = + customRegistryClient + ?? RegistryClient( + configuration: registriesConfiguration, + fingerprintStorage: fingerprints, + fingerprintCheckingMode: FingerprintCheckingMode.map(configuration.fingerprintCheckingMode), + skipSignatureValidation: skipSignatureValidation, + signingEntityStorage: signingEntities, + signingEntityCheckingMode: SigningEntityCheckingMode.map(configuration.signingEntityCheckingMode), + authorizationProvider: registryAuthorizationProvider, + delegate: WorkspaceRegistryClientDelegate(workspaceDelegate: delegate), + checksumAlgorithm: checksumAlgorithm ) - } - - let registriesConfiguration = try customRegistriesConfiguration ?? Workspace.Configuration.Registries( - fileSystem: fileSystem, - localRegistriesFile: location.localRegistriesConfigurationFile, - sharedRegistriesFile: location.sharedRegistriesConfigurationFile - ).configuration - - let registryClient = customRegistryClient ?? RegistryClient( - configuration: registriesConfiguration, - fingerprintStorage: fingerprints, - fingerprintCheckingMode: FingerprintCheckingMode.map(configuration.fingerprintCheckingMode), - skipSignatureValidation: skipSignatureValidation, - signingEntityStorage: signingEntities, - signingEntityCheckingMode: SigningEntityCheckingMode.map(configuration.signingEntityCheckingMode), - authorizationProvider: registryAuthorizationProvider, - delegate: WorkspaceRegistryClientDelegate(workspaceDelegate: delegate), - checksumAlgorithm: checksumAlgorithm - ) // set default registry if not already set by configuration if registryClient.defaultRegistry == nil, let defaultRegistry = configuration.defaultRegistry { @@ -544,15 +562,17 @@ public class Workspace { let registryDownloadsManager = RegistryDownloadsManager( fileSystem: fileSystem, path: location.registryDownloadDirectory, - cachePath: configuration.sharedDependenciesCacheEnabled ? location - .sharedRegistryDownloadsCacheDirectory : .none, + cachePath: configuration.sharedDependenciesCacheEnabled + ? location + .sharedRegistryDownloadsCacheDirectory : .none, registryClient: registryClient, delegate: delegate.map(WorkspaceRegistryDownloadsManagerDelegate.init(workspaceDelegate:)) ) // register the registry dependencies downloader with the cancellation handler cancellator?.register(name: "registry downloads", handler: registryDownloadsManager) - if let transformationMode = RegistryAwareManifestLoader + if let transformationMode = + RegistryAwareManifestLoader .TransformationMode(configuration.sourceControlToRegistryDependencyTransformation) { manifestLoader = RegistryAwareManifestLoader( @@ -567,8 +587,10 @@ public class Workspace { authorizationProvider: authorizationProvider, hostToolchain: hostToolchain, checksumAlgorithm: checksumAlgorithm, - cachePath: customBinaryArtifactsManager?.useCache == false || !configuration - .sharedDependenciesCacheEnabled ? .none : location.sharedBinaryArtifactsCacheDirectory, + cachePath: customBinaryArtifactsManager?.useCache == false + || !configuration + .sharedDependenciesCacheEnabled + ? .none : location.sharedBinaryArtifactsCacheDirectory, customHTTPClient: customBinaryArtifactsManager?.httpClient, customArchiver: customBinaryArtifactsManager?.archiver, delegate: delegate.map(WorkspaceBinaryArtifactsManagerDelegate.init(workspaceDelegate:)) @@ -578,7 +600,7 @@ public class Workspace { var prebuiltsManager: PrebuiltsManager? if configuration.usePrebuilts, - let hostPlatform = customPrebuiltsManager?.hostPlatform ?? PrebuiltsManifest.Platform.hostPlatform + let hostPlatform = customPrebuiltsManager?.hostPlatform ?? PrebuiltsManifest.Platform.hostPlatform { let rootCertPath: AbsolutePath? if let path = configuration.prebuiltsRootCertPath { @@ -777,8 +799,7 @@ extension Workspace { try await self._resolve( root: root, explicitProduct: explicitProduct, - resolvedFileStrategy: forceResolvedVersions ? .lockFile : forceResolution ? .update(forceResolution: true) : - .bestEffort, + resolvedFileStrategy: forceResolvedVersions ? .lockFile : forceResolution ? .update(forceResolution: true) : .bestEffort, observabilityScope: observabilityScope ) } @@ -827,15 +848,16 @@ extension Workspace { } // Compute the custom or extra constraint we need to impose. - let requirement: PackageRequirement = if let version { - .versionSet(.exact(version)) - } else if let branch { - .revision(branch) - } else if let revision { - .revision(revision) - } else { - defaultRequirement - } + let requirement: PackageRequirement = + if let version { + .versionSet(.exact(version)) + } else if let branch { + .revision(branch) + } else if let revision { + .revision(revision) + } else { + defaultRequirement + } // If any products are required, the rest of the package graph will supply those constraints. let constraint = PackageContainerConstraint( @@ -891,8 +913,10 @@ extension Workspace { return } - guard let contents = observabilityScope - .trap({ try fileSystem.getDirectoryContents(self.location.scratchDirectory) }) + guard + let contents = + observabilityScope + .trap({ try fileSystem.getDirectoryContents(self.location.scratchDirectory) }) else { return } @@ -900,10 +924,12 @@ extension Workspace { // Remove all but protected paths. let contentsToRemove = Set(contents).subtracting(protectedAssets) for name in contentsToRemove { - try? self.fileSystem.removeFileTree(AbsolutePath( - validating: name, - relativeTo: self.location.scratchDirectory - )) + try? self.fileSystem.removeFileTree( + AbsolutePath( + validating: name, + relativeTo: self.location.scratchDirectory + ) + ) } } @@ -1016,7 +1042,8 @@ extension Workspace { checkoutPath: $1.checkoutPath, products: $1.products, includePath: $1.includePath, - cModules: $1.cModules) + cModules: $1.cModules + ) for product in $1.products { $0[$1.identity, default: [:]][product] = prebuilt } @@ -1114,8 +1141,6 @@ extension Workspace { } } - - // Check for duplicate root packages after all manifests are loaded. let duplicateRoots = rootManifests.values.spm_findDuplicateElements(by: \.displayName) if let firstDuplicateSet = duplicateRoots.first, let firstDuplicate = firstDuplicateSet.first { @@ -1164,19 +1189,21 @@ extension Workspace { completion: @escaping (Result) -> Void ) { self.loadRootManifests(packages: [path], observabilityScope: observabilityScope) { result in - completion(result.tryMap { - // normally, we call loadRootManifests which attempts to load any manifest it can and report errors via - // diagnostics - // in this case, we want to load a specific manifest, so if the diagnostics contains an error we want to - // throw - guard !observabilityScope.errorsReported else { - throw Diagnostics.fatalError - } - guard let manifest = $0[path] else { - throw InternalError("Unknown manifest for '\(path)'") + completion( + result.tryMap { + // normally, we call loadRootManifests which attempts to load any manifest it can and report errors via + // diagnostics + // in this case, we want to load a specific manifest, so if the diagnostics contains an error we want to + // throw + guard !observabilityScope.errorsReported else { + throw Diagnostics.fatalError + } + guard let manifest = $0[path] else { + throw InternalError("Unknown manifest for '\(path)'") + } + return manifest } - return manifest - }) + ) } } @@ -1401,9 +1428,9 @@ extension Workspace { switch package.kind { case .root, .fileSystem: - break // NOOP + break // NOOP case .localSourceControl: - break // NOOP + break // NOOP case .remoteSourceControl: try await self.removeRepository(dependency: dependencyToRemove) case .registry: @@ -1415,7 +1442,6 @@ extension Workspace { } } - // MARK: - Utility extensions extension Workspace { @@ -1425,7 +1451,7 @@ extension Workspace { public func updateConfiguration(with traitConfiguration: TraitConfiguration) -> Workspace { var newConfig = self.configuration newConfig.traitConfiguration = traitConfiguration - + return Workspace( fileSystem: self.fileSystem, configuration: newConfig, diff --git a/Sources/XCBuildSupport/PIF.swift b/Sources/XCBuildSupport/PIF.swift index d418da1f15c..bb1d6f1b406 100644 --- a/Sources/XCBuildSupport/PIF.swift +++ b/Sources/XCBuildSupport/PIF.swift @@ -95,7 +95,7 @@ public enum PIF { public var projects: [Project] var signature: String? - public init(guid: GUID, name: String, path: AbsolutePath, projects: [Project]) { + public init(guid: GUID, name: String, path: AbsolutePath, projects: [Project]) { precondition(!guid.isEmpty) precondition(!name.isEmpty) precondition(Set(projects.map({ $0.guid })).count == projects.count) @@ -207,7 +207,7 @@ public enum PIF { throw InternalError("Expected to have project signature when encoding for XCBuild") } try container.encode(signature, forKey: "signature") - try contents.encode(targets.map{ $0.signature }, forKey: .targets) + try contents.encode(targets.map { $0.signature }, forKey: .targets) } else { try contents.encode(targets, forKey: .targets) } @@ -413,7 +413,7 @@ public enum PIF { /// The platform filters for this target dependency. public var platformFilters: [PlatformFilter] - public init(targetGUID: String, platformFilters: [PlatformFilter] = []) { + public init(targetGUID: String, platformFilters: [PlatformFilter] = []) { self.targetGUID = targetGUID self.platformFilters = platformFilters } @@ -657,7 +657,7 @@ public enum PIF { self.productType = .packageProduct self.productName = "" let fwkBuildPhase = try container.decodeIfPresent(FrameworksBuildPhase.self, forKey: .frameworksBuildPhase) - buildPhases = fwkBuildPhase.map{ [$0] } ?? [] + buildPhases = fwkBuildPhase.map { [$0] } ?? [] impartedBuildProperties = ImpartedBuildProperties(settings: BuildSettings()) } else if type == "standard" { self.productType = try container.decode(ProductType.self, forKey: .productTypeIdentifier) @@ -1240,7 +1240,7 @@ extension PIF.FileReference { default: return pathExtension.flatMap({ pathExtension in - XCBuildFileType.allCases.first(where:{ $0.fileTypes.contains(pathExtension) }) + XCBuildFileType.allCases.first(where: { $0.fileTypes.contains(pathExtension) }) })?.fileTypeIdentifier ?? "file" } } @@ -1279,7 +1279,7 @@ extension PIF { } let projects = workspace.projects - try projects.flatMap{ $0.targets }.forEach(sign) + try projects.flatMap { $0.targets }.forEach(sign) try projects.forEach(sign) try sign(workspace) } diff --git a/Sources/XCBuildSupport/PIFBuilder.swift b/Sources/XCBuildSupport/PIFBuilder.swift index 1b231f68592..840a0a8d6d8 100644 --- a/Sources/XCBuildSupport/PIFBuilder.swift +++ b/Sources/XCBuildSupport/PIFBuilder.swift @@ -17,8 +17,7 @@ import PackageLoading import PackageModel import TSCUtility -@_spi(SwiftPMInternal) -import SPMBuildCore +@_spi(SwiftPMInternal) import SPMBuildCore import func TSCBasic.memoize import func TSCBasic.topologicalSort @@ -119,7 +118,7 @@ public final class PIFBuilder { let rootPackage = self.graph.rootPackages[self.graph.rootPackages.startIndex] let sortedPackages = self.graph.packages - .sorted { $0.manifest.displayName < $1.manifest.displayName } // TODO: use identity instead? + .sorted { $0.manifest.displayName < $1.manifest.displayName } // TODO: use identity instead? var projects: [PIFProjectBuilder] = try sortedPackages.map { package in try PackagePIFProjectBuilder( package: package, @@ -133,7 +132,7 @@ public final class PIFBuilder { let workspace = try PIF.Workspace( guid: "Workspace:\(rootPackage.path.pathString)", - name: rootPackage.manifest.displayName, // TODO: use identity instead? + name: rootPackage.manifest.displayName, // TODO: use identity instead? path: rootPackage.path, projects: projects.map { try $0.construct() } ) @@ -189,7 +188,8 @@ class PIFProjectBuilder { func addBuildConfiguration( name: String, settings: PIF.BuildSettings = PIF.BuildSettings(), - impartedBuildProperties: PIF.ImpartedBuildProperties = PIF + impartedBuildProperties: PIF.ImpartedBuildProperties = + PIF .ImpartedBuildProperties(settings: PIF.BuildSettings()) ) -> PIFBuildConfigurationBuilder { let builder = PIFBuildConfigurationBuilder( @@ -281,7 +281,7 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { super.init() self.guid = package.pifProjectGUID - self.name = package.manifest.displayName // TODO: use identity instead? + self.name = package.manifest.displayName // TODO: use identity instead? self.path = package.path self.projectDirectory = package.path self.developmentRegion = package.manifest.defaultLocalization ?? "en" @@ -618,8 +618,8 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { // Set the project and marketing version for the framework because the app store requires these to be // present. The AppStore requires bumping the project version when ingesting new builds but that's for // top-level apps and not frameworks embedded inside it. - settings[.MARKETING_VERSION] = "1.0" // Version - settings[.CURRENT_PROJECT_VERSION] = "1" // Build + settings[.MARKETING_VERSION] = "1.0" // Version + settings[.CURRENT_PROJECT_VERSION] = "1" // Build } pifTarget.addSourcesBuildPhase() @@ -677,11 +677,11 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { ["-Xcc", "-fmodule-map-file=\(moduleMapFile)"] moduleMapFileContents = """ - module \(target.c99name) { - umbrella "\(clangTarget.includeDir.pathString)" - export * - } - """ + module \(target.c99name) { + umbrella "\(clangTarget.includeDir.pathString)" + export * + } + """ shouldImpartModuleMap = true } else { @@ -699,11 +699,11 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { settings.addCommonSwiftSettings(package: self.package, target: target, parameters: self.parameters) moduleMapFileContents = """ - module \(target.c99name) { - header "\(target.name)-Swift.h" - export * - } - """ + module \(target.c99name) { + header "\(target.name)-Swift.h" + export * + } + """ shouldImpartModuleMap = true } else { @@ -900,7 +900,7 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { return nil } - let bundleName = "\(package.manifest.displayName)_\(target.name)" // TODO: use identity instead? + let bundleName = "\(package.manifest.displayName)_\(target.name)" // TODO: use identity instead? let resourcesTarget = self.addTarget( guid: target.pifResourceTargetGUID, name: bundleName, @@ -919,7 +919,7 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { settings[.PRODUCT_NAME] = "$(TARGET_NAME)" settings[.PRODUCT_MODULE_NAME] = bundleName let bundleIdentifier = "\(package.manifest.displayName).\(target.name).resources" - .spm_mangledToBundleIdentifier() // TODO: use identity instead? + .spm_mangledToBundleIdentifier() // TODO: use identity instead? settings[.PRODUCT_BUNDLE_IDENTIFIER] = bundleIdentifier settings[.GENERATE_INFOPLIST_FILE] = "YES" settings[.PACKAGE_RESOURCE_TARGET_KIND] = "resource" @@ -955,10 +955,12 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { } let targetGroup = groupTree.addGroup(path: "/", sourceTree: .group) - pifTarget.addResourceFile(targetGroup.addFileReference( - path: "\(bundleName)\(parameters.triple.nsbundleExtension)", - sourceTree: .builtProductsDir - )) + pifTarget.addResourceFile( + targetGroup.addFileReference( + path: "\(bundleName)\(parameters.triple.nsbundleExtension)", + sourceTree: .builtProductsDir + ) + ) return bundleName } @@ -989,7 +991,8 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { for assignment in assignments { var value = assignment.value if setting == .HEADER_SEARCH_PATHS { - value = try value + value = + try value .map { try AbsolutePath(validating: $0, relativeTo: target.sources.root).pathString } } @@ -1226,7 +1229,8 @@ class PIFBaseTargetBuilder { public func addBuildConfiguration( name: String, settings: PIF.BuildSettings = PIF.BuildSettings(), - impartedBuildProperties: PIF.ImpartedBuildProperties = PIF + impartedBuildProperties: PIF.ImpartedBuildProperties = + PIF .ImpartedBuildProperties(settings: PIF.BuildSettings()) ) -> PIFBuildConfigurationBuilder { let builder = PIFBuildConfigurationBuilder( @@ -1283,7 +1287,8 @@ class PIFBaseTargetBuilder { func addDependency(toTargetWithGUID targetGUID: String, platformFilters: [PIF.PlatformFilter], linkProduct: Bool) { self.dependencies.append(.init(targetGUID: targetGUID, platformFilters: platformFilters)) if linkProduct { - let frameworksPhase = self.buildPhases.first { $0 is PIFFrameworksBuildPhaseBuilder } + let frameworksPhase = + self.buildPhases.first { $0 is PIFFrameworksBuildPhaseBuilder } ?? self.addFrameworksBuildPhase() frameworksPhase.addBuildFile(toTargetWithGUID: targetGUID, platformFilters: platformFilters) } @@ -1312,14 +1317,18 @@ class PIFBaseTargetBuilder { _ fileReference: PIFFileReferenceBuilder, platformFilters: [PIF.PlatformFilter] ) -> PIFBuildFileBuilder { - let frameworksPhase = self.buildPhases.first { $0 is PIFFrameworksBuildPhaseBuilder } ?? self + let frameworksPhase = + self.buildPhases.first { $0 is PIFFrameworksBuildPhaseBuilder } + ?? self .addFrameworksBuildPhase() return frameworksPhase.addBuildFile(to: fileReference, platformFilters: platformFilters) } @discardableResult public func addResourceFile(_ fileReference: PIFFileReferenceBuilder) -> PIFBuildFileBuilder { - let resourcesPhase = self.buildPhases.first { $0 is PIFResourcesBuildPhaseBuilder } ?? self + let resourcesPhase = + self.buildPhases.first { $0 is PIFResourcesBuildPhaseBuilder } + ?? self .addResourcesBuildPhase() return resourcesPhase.addBuildFile(to: fileReference, platformFilters: []) } @@ -1771,7 +1780,7 @@ extension PIF.PlatformFilter { /// Mac Catalyst platform filters. public static let macCatalystFilters: [PIF.PlatformFilter] = [ - .init(platform: "ios", environment: "maccatalyst"), + .init(platform: "ios", environment: "maccatalyst") ] /// iOS platform filters. @@ -1794,7 +1803,7 @@ extension PIF.PlatformFilter { /// DriverKit platform filters. public static let driverKitFilters: [PIF.PlatformFilter] = [ - .init(platform: "driverkit"), + .init(platform: "driverkit") ] /// Windows platform filters. @@ -1816,17 +1825,17 @@ extension PIF.PlatformFilter { /// OpenBSD filters. public static let openBSDFilters: [PIF.PlatformFilter] = [ - .init(platform: "openbsd"), + .init(platform: "openbsd") ] /// FreeBSD filters. public static let freeBSDFilters: [PIF.PlatformFilter] = [ - .init(platform: "freebsd"), + .init(platform: "freebsd") ] /// WebAssembly platform filters. public static let webAssemblyFilters: [PIF.PlatformFilter] = [ - .init(platform: "wasi"), + .init(platform: "wasi") ] /// VisionOS platform filters. @@ -1904,9 +1913,11 @@ extension PIF.BuildSettings { // We have to normalize to two component strings to match the results from XCBuild w.r.t. to hashing of // `SwiftLanguageVersion` instances. - let normalizedDeclaredVersions = Set(target.declaredSwiftVersions.compactMap { - SwiftLanguageVersion(string: "\($0.major).\($0.minor)") - }) + let normalizedDeclaredVersions = Set( + target.declaredSwiftVersions.compactMap { + SwiftLanguageVersion(string: "\($0.major).\($0.minor)") + } + ) let declaredSwiftVersions = Array( normalizedDeclaredVersions diff --git a/Sources/XCBuildSupport/XcodeBuildSystem.swift b/Sources/XCBuildSupport/XcodeBuildSystem.swift index bca5b48446a..3ab0ff93144 100644 --- a/Sources/XCBuildSupport/XcodeBuildSystem.swift +++ b/Sources/XCBuildSupport/XcodeBuildSystem.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics import Dispatch import class Foundation.JSONEncoder import class Foundation.NSArray @@ -19,8 +18,7 @@ import class Foundation.NSDictionary import PackageGraph import PackageModel -@_spi(SwiftPMInternal) -import SPMBuildCore +@_spi(SwiftPMInternal) import SPMBuildCore import class Basics.AsyncProcess import func TSCBasic.memoize @@ -142,19 +140,20 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem { false } } - let supportedSwiftVersions: [SwiftLanguageVersion] = if let versions = - compilerSpec?["SupportedLanguageVersions"] as? NSArray - { - versions.compactMap { - if let stringValue = $0 as? String { - SwiftLanguageVersion(string: stringValue) - } else { - nil + let supportedSwiftVersions: [SwiftLanguageVersion] = + if let versions = + compilerSpec?["SupportedLanguageVersions"] as? NSArray + { + versions.compactMap { + if let stringValue = $0 as? String { + SwiftLanguageVersion(string: stringValue) + } else { + nil + } } + } else { + [] } - } else { - [] - } return supportedSwiftVersions } return [] @@ -205,16 +204,19 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem { var hasStdout = false var stdoutBuffer: [UInt8] = [] var stderrBuffer: [UInt8] = [] - let redirection: AsyncProcess.OutputRedirection = .stream(stdout: { bytes in - hasStdout = hasStdout || !bytes.isEmpty - delegate.parse(bytes: bytes) + let redirection: AsyncProcess.OutputRedirection = .stream( + stdout: { bytes in + hasStdout = hasStdout || !bytes.isEmpty + delegate.parse(bytes: bytes) - if !delegate.didParseAnyOutput { - stdoutBuffer.append(contentsOf: bytes) + if !delegate.didParseAnyOutput { + stdoutBuffer.append(contentsOf: bytes) + } + }, + stderr: { bytes in + stderrBuffer.append(contentsOf: bytes) } - }, stderr: { bytes in - stderrBuffer.append(contentsOf: bytes) - }) + ) // We need to sanitize the environment we are passing to XCBuild because we could otherwise interfere with its // linked dependencies e.g. when we have a custom swift-driver dynamic library in the path. @@ -275,26 +277,22 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem { // native build system. settings["SWIFT_EXEC"] = buildParameters.toolchain.swiftCompilerPath.pathString settings["LIBRARY_SEARCH_PATHS"] = try "$(inherited) \(buildParameters.toolchain.toolchainLibDir.pathString)" - settings["OTHER_CFLAGS"] = ( - ["$(inherited)"] - + buildParameters.toolchain.extraFlags.cCompilerFlags.map { $0.spm_shellEscaped() } - + buildParameters.flags.cCompilerFlags.map { $0.spm_shellEscaped() } - ).joined(separator: " ") - settings["OTHER_CPLUSPLUSFLAGS"] = ( - ["$(inherited)"] - + buildParameters.toolchain.extraFlags.cxxCompilerFlags.map { $0.spm_shellEscaped() } - + buildParameters.flags.cxxCompilerFlags.map { $0.spm_shellEscaped() } - ).joined(separator: " ") - settings["OTHER_SWIFT_FLAGS"] = ( - ["$(inherited)"] - + buildParameters.toolchain.extraFlags.swiftCompilerFlags.map { $0.spm_shellEscaped() } - + buildParameters.flags.swiftCompilerFlags.map { $0.spm_shellEscaped() } - ).joined(separator: " ") - settings["OTHER_LDFLAGS"] = ( - ["$(inherited)"] - + buildParameters.toolchain.extraFlags.linkerFlags.map { $0.spm_shellEscaped() } - + buildParameters.flags.linkerFlags.map { $0.spm_shellEscaped() } - ).joined(separator: " ") + settings["OTHER_CFLAGS"] = + (["$(inherited)"] + + buildParameters.toolchain.extraFlags.cCompilerFlags.map { $0.spm_shellEscaped() } + + buildParameters.flags.cCompilerFlags.map { $0.spm_shellEscaped() }).joined(separator: " ") + settings["OTHER_CPLUSPLUSFLAGS"] = + (["$(inherited)"] + + buildParameters.toolchain.extraFlags.cxxCompilerFlags.map { $0.spm_shellEscaped() } + + buildParameters.flags.cxxCompilerFlags.map { $0.spm_shellEscaped() }).joined(separator: " ") + settings["OTHER_SWIFT_FLAGS"] = + (["$(inherited)"] + + buildParameters.toolchain.extraFlags.swiftCompilerFlags.map { $0.spm_shellEscaped() } + + buildParameters.flags.swiftCompilerFlags.map { $0.spm_shellEscaped() }).joined(separator: " ") + settings["OTHER_LDFLAGS"] = + (["$(inherited)"] + + buildParameters.toolchain.extraFlags.linkerFlags.map { $0.spm_shellEscaped() } + + buildParameters.flags.linkerFlags.map { $0.spm_shellEscaped() }).joined(separator: " ") // Optionally also set the list of architectures to build for. if let architectures = buildParameters.architectures, !architectures.isEmpty { diff --git a/Sources/_AsyncFileSystem/ConcurrencySupport.swift b/Sources/_AsyncFileSystem/ConcurrencySupport.swift index c42fb1066b8..40867d4188b 100644 --- a/Sources/_AsyncFileSystem/ConcurrencySupport.swift +++ b/Sources/_AsyncFileSystem/ConcurrencySupport.swift @@ -1,4 +1,3 @@ - //===----------------------------------------------------------------------===// // // This source file is part of the Swift open source project diff --git a/Sources/_AsyncFileSystem/OSFileSystem.swift b/Sources/_AsyncFileSystem/OSFileSystem.swift index b749a07e548..0c1f5295c75 100644 --- a/Sources/_AsyncFileSystem/OSFileSystem.swift +++ b/Sources/_AsyncFileSystem/OSFileSystem.swift @@ -14,56 +14,56 @@ import Foundation @preconcurrency package import SystemPackage public actor OSFileSystem: AsyncFileSystem { - public static let defaultChunkSize = 512 * 1024 + public static let defaultChunkSize = 512 * 1024 - let readChunkSize: Int - private let ioQueue = DispatchQueue(label: "org.swift.sdk-generator-io") + let readChunkSize: Int + private let ioQueue = DispatchQueue(label: "org.swift.sdk-generator-io") - package init(readChunkSize: Int = defaultChunkSize) { - self.readChunkSize = readChunkSize - } + package init(readChunkSize: Int = defaultChunkSize) { + self.readChunkSize = readChunkSize + } - package func withOpenReadableFile( - _ path: FilePath, - _ body: (OpenReadableFile) async throws -> T - ) async throws -> T { - let fd = try FileDescriptor.open(path, .readOnly) - // Can't use ``FileDescriptor//closeAfter` here, as that doesn't support async closures. - do { - let result = try await body(.init(chunkSize: readChunkSize, fileHandle: .real(fd, self.ioQueue))) - try fd.close() - return result - } catch { - try fd.close() - throw error.attach(path) + package func withOpenReadableFile( + _ path: FilePath, + _ body: (OpenReadableFile) async throws -> T + ) async throws -> T { + let fd = try FileDescriptor.open(path, .readOnly) + // Can't use ``FileDescriptor//closeAfter` here, as that doesn't support async closures. + do { + let result = try await body(.init(chunkSize: readChunkSize, fileHandle: .real(fd, self.ioQueue))) + try fd.close() + return result + } catch { + try fd.close() + throw error.attach(path) + } } - } - package func withOpenWritableFile( - _ path: FilePath, - _ body: (OpenWritableFile) async throws -> T - ) async throws -> T { - let fd = try FileDescriptor.open( - path, - .writeOnly, - options: [.create, .truncate], - permissions: [ - .groupRead, - .otherRead, - .ownerReadWrite - ] - ) - do { - let result = try await body(.init(storage: .real(fd, self.ioQueue), path: path)) - try fd.close() - return result - } catch { - try fd.close() - throw error.attach(path) + package func withOpenWritableFile( + _ path: FilePath, + _ body: (OpenWritableFile) async throws -> T + ) async throws -> T { + let fd = try FileDescriptor.open( + path, + .writeOnly, + options: [.create, .truncate], + permissions: [ + .groupRead, + .otherRead, + .ownerReadWrite, + ] + ) + do { + let result = try await body(.init(storage: .real(fd, self.ioQueue), path: path)) + try fd.close() + return result + } catch { + try fd.close() + throw error.attach(path) + } } - } - package func exists(_ path: SystemPackage.FilePath) async -> Bool { - FileManager.default.fileExists(atPath: path.string) - } + package func exists(_ path: SystemPackage.FilePath) async -> Bool { + FileManager.default.fileExists(atPath: path.string) + } } diff --git a/Sources/_AsyncFileSystem/OpenReadableFile.swift b/Sources/_AsyncFileSystem/OpenReadableFile.swift index 11cb298c80c..935755f0016 100644 --- a/Sources/_AsyncFileSystem/OpenReadableFile.swift +++ b/Sources/_AsyncFileSystem/OpenReadableFile.swift @@ -30,7 +30,7 @@ package struct OpenReadableFile: Sendable { /// Concrete instance of underlying file storage. let fileHandle: Storage - + /// Creates a readable ``AsyncSequence`` that can be iterated on to read from this file handle. /// - Returns: `ReadableFileStream` value conforming to ``AsyncSequence``, ready for asynchronous iteration. package func read() async throws -> ReadableFileStream { @@ -43,7 +43,7 @@ package struct OpenReadableFile: Sendable { readChunkSize: self.chunkSize ) ) - + case .mock(let array): return ReadableFileStream.mock(.init(bytes: array, chunkSize: self.chunkSize)) } diff --git a/Sources/_AsyncFileSystem/OpenWritableFile.swift b/Sources/_AsyncFileSystem/OpenWritableFile.swift index 7f3f947db7c..dec8a7712fe 100644 --- a/Sources/_AsyncFileSystem/OpenWritableFile.swift +++ b/Sources/_AsyncFileSystem/OpenWritableFile.swift @@ -21,11 +21,11 @@ package actor OpenWritableFile: WritableStream { /// Operating system file descriptor and a queue used for reading from that file descriptor without blocking /// the Swift Concurrency thread pool. case real(FileDescriptor, DispatchQueue) - + /// Reference to the ``MockFileSystem`` actor that provides file storage. case mock(MockFileSystem) } - + /// Concrete instance of underlying storage. let storage: Storage @@ -34,7 +34,7 @@ package actor OpenWritableFile: WritableStream { /// Whether the underlying file descriptor has been closed. private var isClosed = false - + /// Creates a new write-only file handle. /// - Parameters: /// - storage: Underlying storage for the file. @@ -43,7 +43,7 @@ package actor OpenWritableFile: WritableStream { self.storage = storage self.path = path } - + /// Writes a sequence of bytes to the buffer. package func write(_ bytes: some Collection & Sendable) async throws { assert(!isClosed) @@ -76,4 +76,3 @@ package actor OpenWritableFile: WritableStream { } } } - diff --git a/Sources/_AsyncFileSystem/ReadableFileStream.swift b/Sources/_AsyncFileSystem/ReadableFileStream.swift index f218e970ede..3cf5a5c2763 100644 --- a/Sources/_AsyncFileSystem/ReadableFileStream.swift +++ b/Sources/_AsyncFileSystem/ReadableFileStream.swift @@ -89,7 +89,6 @@ package struct RealReadableFileStream: AsyncSequence { } } - /// A stream of file contents backed by an in-memory array of bytes. package struct MockReadableFileStream: AsyncSequence { package typealias Element = ArraySlice diff --git a/Sources/_IntegrationTestSupport/Helpers.swift b/Sources/_IntegrationTestSupport/Helpers.swift index 7dd29842e09..05148620bc3 100644 --- a/Sources/_IntegrationTestSupport/Helpers.swift +++ b/Sources/_IntegrationTestSupport/Helpers.swift @@ -22,11 +22,11 @@ public let sdkRoot: AbsolutePath? = { } #if os(macOS) - let result = try! AsyncProcess.popen(arguments: ["xcrun", "--sdk", "macosx", "--show-sdk-path"]) - let sdkRoot = try! AbsolutePath(validating: result.utf8Output().spm_chomp()) - return sdkRoot + let result = try! AsyncProcess.popen(arguments: ["xcrun", "--sdk", "macosx", "--show-sdk-path"]) + let sdkRoot = try! AbsolutePath(validating: result.utf8Output().spm_chomp()) + return sdkRoot #else - return nil + return nil #endif }() @@ -36,13 +36,13 @@ public let toolchainPath: AbsolutePath = { } #if os(macOS) - let swiftcPath = try! AbsolutePath( - validating: sh("xcrun", "--find", "swift").stdout.spm_chomp() - ) + let swiftcPath = try! AbsolutePath( + validating: sh("xcrun", "--find", "swift").stdout.spm_chomp() + ) #elseif os(Windows) - let swiftcPath = try! AbsolutePath(validating: sh("where.exe", "swift.exe").stdout.spm_chomp()) + let swiftcPath = try! AbsolutePath(validating: sh("where.exe", "swift.exe").stdout.spm_chomp()) #else - let swiftcPath = try! AbsolutePath(validating: sh("which", "swift").stdout.spm_chomp()) + let swiftcPath = try! AbsolutePath(validating: sh("which", "swift").stdout.spm_chomp()) #endif let toolchainPath = swiftcPath.parentDirectory.parentDirectory.parentDirectory return toolchainPath @@ -59,12 +59,12 @@ public let clang: AbsolutePath = { public let xcodebuild: AbsolutePath = { #if os(macOS) - let xcodebuildPath = try! AbsolutePath( - validating: sh("xcrun", "--find", "xcodebuild").stdout.spm_chomp() - ) - return xcodebuildPath + let xcodebuildPath = try! AbsolutePath( + validating: sh("xcrun", "--find", "xcodebuild").stdout.spm_chomp() + ) + return xcodebuildPath #else - fatalError("should not be used on other platforms than macOS") + fatalError("should not be used on other platforms than macOS") #endif }() @@ -107,7 +107,8 @@ package func _sh( } let result = try AsyncProcess.popen( - arguments: arguments.map(\.description), environment: environment + arguments: arguments.map(\.description), + environment: environment ) return result } @@ -124,13 +125,26 @@ public func binaryTargetsFixture(_ closure: (AbsolutePath) async throws -> Void) let headersPath = subpath.appending(component: "include") let libraryPath = tmpDir.appending(component: "libStaticLibrary.a") try sh( - clang, "-c", sourcePath, "-I", headersPath, "-fobjc-arc", "-fmodules", "-o", + clang, + "-c", + sourcePath, + "-I", + headersPath, + "-fobjc-arc", + "-fmodules", + "-o", libraryPath ) let xcframeworkPath = packagePath.appending(component: "StaticLibrary.xcframework") try sh( - xcodebuild, "-create-xcframework", "-library", libraryPath, "-headers", headersPath, - "-output", xcframeworkPath + xcodebuild, + "-create-xcframework", + "-library", + libraryPath, + "-headers", + headersPath, + "-output", + xcframeworkPath ) } @@ -141,13 +155,26 @@ public func binaryTargetsFixture(_ closure: (AbsolutePath) async throws -> Void) let headersPath = subpath.appending(component: "include") let libraryPath = tmpDir.appending(component: "libDynamicLibrary.dylib") try sh( - clang, sourcePath, "-I", headersPath, "-fobjc-arc", "-fmodules", "-dynamiclib", - "-o", libraryPath + clang, + sourcePath, + "-I", + headersPath, + "-fobjc-arc", + "-fmodules", + "-dynamiclib", + "-o", + libraryPath ) let xcframeworkPath = packagePath.appending(component: "DynamicLibrary.xcframework") try sh( - xcodebuild, "-create-xcframework", "-library", libraryPath, "-headers", headersPath, - "-output", xcframeworkPath + xcodebuild, + "-create-xcframework", + "-library", + libraryPath, + "-headers", + headersPath, + "-output", + xcframeworkPath ) } @@ -156,8 +183,15 @@ public func binaryTargetsFixture(_ closure: (AbsolutePath) async throws -> Void) let subpath = inputsPath.appending(component: "SwiftFramework") let projectPath = subpath.appending(component: "SwiftFramework.xcodeproj") try sh( - xcodebuild, "-project", projectPath, "-scheme", "SwiftFramework", - "-derivedDataPath", tmpDir, "COMPILER_INDEX_STORE_ENABLE=NO", "DEPLOYMENT_LOCATION=NO" + xcodebuild, + "-project", + projectPath, + "-scheme", + "SwiftFramework", + "-derivedDataPath", + tmpDir, + "COMPILER_INDEX_STORE_ENABLE=NO", + "DEPLOYMENT_LOCATION=NO" ) let frameworkPath = try AbsolutePath( validating: "Build/Products/Debug/SwiftFramework.framework", @@ -165,7 +199,11 @@ public func binaryTargetsFixture(_ closure: (AbsolutePath) async throws -> Void) ) let xcframeworkPath = packagePath.appending(component: "SwiftFramework.xcframework") try sh( - xcodebuild, "-create-xcframework", "-framework", frameworkPath, "-output", + xcodebuild, + "-create-xcframework", + "-framework", + frameworkPath, + "-output", xcframeworkPath ) } diff --git a/Sources/_InternalBuildTestSupport/MockBuildTestHelper.swift b/Sources/_InternalBuildTestSupport/MockBuildTestHelper.swift index 8354b6e19ce..9b4eeffdf0d 100644 --- a/Sources/_InternalBuildTestSupport/MockBuildTestHelper.swift +++ b/Sources/_InternalBuildTestSupport/MockBuildTestHelper.swift @@ -12,8 +12,7 @@ import Basics -@_spi(SwiftPMInternal) -import Build +@_spi(SwiftPMInternal) import Build import _InternalTestSupport import struct PackageGraph.ModulesGraph @@ -77,18 +76,19 @@ public func mockBuildPlan( if let platform { precondition(triple == nil) - inferredTriple = switch platform { - case .macOS: - Triple.x86_64MacOS - case .linux: - Triple.arm64Linux - case .android: - Triple.arm64Android - case .windows: - Triple.windows - default: - fatalError("unsupported platform in tests") - } + inferredTriple = + switch platform { + case .macOS: + Triple.x86_64MacOS + case .linux: + Triple.arm64Linux + case .android: + Triple.arm64Android + case .windows: + Triple.windows + default: + fatalError("unsupported platform in tests") + } } else { inferredTriple = triple ?? hostTriple } @@ -185,7 +185,7 @@ public struct BuildPlanResult { sourceLocation: SourceLocation = #_sourceLocation, ) { if Test.current != nil { - #expect(self.targetMap.count == count, sourceLocation: sourceLocation) + #expect(self.targetMap.count == count, sourceLocation: sourceLocation) } else { XCTAssertEqual(self.targetMap.count, count, file: file, line: line) } @@ -198,7 +198,7 @@ public struct BuildPlanResult { sourceLocation: SourceLocation = #_sourceLocation, ) { if Test.current != nil { - #expect(self.productMap.count == count, sourceLocation: sourceLocation) + #expect(self.productMap.count == count, sourceLocation: sourceLocation) } else { XCTAssertEqual(self.productMap.count, count, file: file, line: line) } diff --git a/Sources/_InternalBuildTestSupport/PIFTester.swift b/Sources/_InternalBuildTestSupport/PIFTester.swift index 24fd1e7b716..a049ace8d32 100644 --- a/Sources/_InternalBuildTestSupport/PIFTester.swift +++ b/Sources/_InternalBuildTestSupport/PIFTester.swift @@ -193,32 +193,38 @@ public class PIFBaseTargetTester { dependencies = Set(baseTarget.dependencies.map { targetMap[$0.targetGUID]!.guid }) let sourcesBuildFiles = baseTarget.buildPhases.first { $0 is PIF.SourcesBuildPhase }?.buildFiles ?? [] - sources = Set(sourcesBuildFiles.map { buildFile -> String in - if case .file(let guid) = buildFile.reference { - return fileMap[guid]! - } else { - fatalError("unexpected build file reference: \(buildFile)") + sources = Set( + sourcesBuildFiles.map { buildFile -> String in + if case .file(let guid) = buildFile.reference { + return fileMap[guid]! + } else { + fatalError("unexpected build file reference: \(buildFile)") + } } - }) + ) let frameworksBuildFiles = baseTarget.buildPhases.first { $0 is PIF.FrameworksBuildPhase }?.buildFiles ?? [] - frameworks = Set(frameworksBuildFiles.map { buildFile -> String in - switch buildFile.reference { - case .target(let guid): - return targetMap[guid]!.guid - case .file(let guid): - return fileMap[guid]! + frameworks = Set( + frameworksBuildFiles.map { buildFile -> String in + switch buildFile.reference { + case .target(let guid): + return targetMap[guid]!.guid + case .file(let guid): + return fileMap[guid]! + } } - }) + ) let resourcesBuildFiles = baseTarget.buildPhases.first { $0 is PIF.ResourcesBuildPhase }?.buildFiles ?? [] - resources = Set(resourcesBuildFiles.map { buildFile -> String in - if case .file(let guid) = buildFile.reference { - return fileMap[guid]! - } else { - fatalError("unexpected build file reference: \(buildFile)") + resources = Set( + resourcesBuildFiles.map { buildFile -> String in + if case .file(let guid) = buildFile.reference { + return fileMap[guid]! + } else { + fatalError("unexpected build file reference: \(buildFile)") + } } - }) + ) } public func checkBuildConfiguration( @@ -367,8 +373,7 @@ public final class PIFBuildSettingsTester { public func checkUncheckedSettings(file: StaticString = #file, line: UInt = #line, sourceLocation: SourceLocation = #_sourceLocation) { let uncheckedKeys = - Array(buildSettings.singleValueSettings.keys.map { $0.rawValue }) + - Array(buildSettings.multipleValueSettings.keys.map { $0.rawValue }) + Array(buildSettings.singleValueSettings.keys.map { $0.rawValue }) + Array(buildSettings.multipleValueSettings.keys.map { $0.rawValue }) if Test.current != nil { #expect( uncheckedKeys.isEmpty, @@ -383,7 +388,8 @@ public final class PIFBuildSettingsTester { let uncheckedKeys = Array(settings.keys.map { $0.rawValue }) if Test.current != nil { #expect( - uncheckedKeys.isEmpty, "\(platform) settings are left unchecked: \(uncheckedKeys)", + uncheckedKeys.isEmpty, + "\(platform) settings are left unchecked: \(uncheckedKeys)", sourceLocation: sourceLocation, ) } else { @@ -395,7 +401,8 @@ public final class PIFBuildSettingsTester { let uncheckedKeys = Array(settings.keys.map { $0.rawValue }) if Test.current != nil { #expect( - uncheckedKeys.isEmpty, "\(platform) settings are left unchecked: \(uncheckedKeys)", + uncheckedKeys.isEmpty, + "\(platform) settings are left unchecked: \(uncheckedKeys)", sourceLocation: sourceLocation, ) } else { diff --git a/Sources/_InternalTestSupport/BuildSystemProvider+Configuration.swift b/Sources/_InternalTestSupport/BuildSystemProvider+Configuration.swift index 30b3db4b2c7..92dfaab7e68 100644 --- a/Sources/_InternalTestSupport/BuildSystemProvider+Configuration.swift +++ b/Sources/_InternalTestSupport/BuildSystemProvider+Configuration.swift @@ -21,19 +21,19 @@ extension BuildSystemProvider.Kind { let suffix: String #if os(Linux) - suffix = "-linux" + suffix = "-linux" #elseif os(Windows) - suffix = "-windows" + suffix = "-windows" #else - suffix = "" + suffix = "" #endif switch self { - case .native: - return ["\(config)".lowercased()] - case .swiftbuild: - return ["Products" , "\(config)".capitalized + suffix] - case .xcode: - return ["apple", "Products" , "\(config)".capitalized + suffix] + case .native: + return ["\(config)".lowercased()] + case .swiftbuild: + return ["Products", "\(config)".capitalized + suffix] + case .xcode: + return ["apple", "Products", "\(config)".capitalized + suffix] } } diff --git a/Sources/_InternalTestSupport/CombinationsWithRepetition.swift b/Sources/_InternalTestSupport/CombinationsWithRepetition.swift index 4855780db63..c077658b47c 100644 --- a/Sources/_InternalTestSupport/CombinationsWithRepetition.swift +++ b/Sources/_InternalTestSupport/CombinationsWithRepetition.swift @@ -9,7 +9,7 @@ */ import Foundation -package struct CombinationsWithRepetition : Sequence { +package struct CombinationsWithRepetition: Sequence { let base: C let length: Int @@ -19,7 +19,7 @@ package struct CombinationsWithRepetition : Sequence { self.length = length } - package struct Iterator : IteratorProtocol { + package struct Iterator: IteratorProtocol { let base: C var firstIteration = true diff --git a/Sources/_InternalTestSupport/FileSystemHelpers.swift b/Sources/_InternalTestSupport/FileSystemHelpers.swift index 5f08a6ff35e..0dd137cc474 100644 --- a/Sources/_InternalTestSupport/FileSystemHelpers.swift +++ b/Sources/_InternalTestSupport/FileSystemHelpers.swift @@ -48,20 +48,21 @@ public func getFiles( ) throws -> [AbsolutePath] { var matchingFiles: [AbsolutePath] = [] let normalizedExtension = `extension`.lowercased() - + guard fileSystem.exists(directory) else { throw StringError("Directory does not exist: \(directory)") } - + guard fileSystem.isDirectory(directory) else { throw StringError("Path is not a directory: \(directory)") } - + if recursive { try fileSystem.enumerate(directory: directory) { filePath in if fileSystem.isFile(filePath) { if let fileExtension = filePath.extension?.lowercased(), - fileExtension == normalizedExtension { + fileExtension == normalizedExtension + { matchingFiles.append(filePath) } } @@ -73,13 +74,14 @@ public func getFiles( let itemPath = directory.appending(component: item) if fileSystem.isFile(itemPath) { if let fileExtension = itemPath.extension?.lowercased(), - fileExtension == normalizedExtension { + fileExtension == normalizedExtension + { matchingFiles.append(itemPath) } } } } - + return matchingFiles } @@ -102,7 +104,7 @@ public func getFiles( guard let currentWorkingDirectory = fileSystem.currentWorkingDirectory else { throw StringError("Cannot determine current working directory") } - + let absoluteDirectory = currentWorkingDirectory.appending(directory) let absoluteResults = try getFiles( in: absoluteDirectory, @@ -110,7 +112,7 @@ public func getFiles( recursive: recursive, fileSystem: fileSystem ) - + // Convert results back to RelativePath return absoluteResults.map { absolutePath in absolutePath.relative(to: currentWorkingDirectory) diff --git a/Sources/_InternalTestSupport/GitRepositoryExtensions.swift b/Sources/_InternalTestSupport/GitRepositoryExtensions.swift index 46a83a67aa1..a51959fd88f 100644 --- a/Sources/_InternalTestSupport/GitRepositoryExtensions.swift +++ b/Sources/_InternalTestSupport/GitRepositoryExtensions.swift @@ -28,13 +28,24 @@ package extension GitRepository { /// Returns current branch name. If HEAD is on a detached state, this returns HEAD. func currentBranch() throws -> String { return try AsyncProcess.checkNonZeroExit( - args: Git.tool, "-C", path.pathString, "rev-parse", "--abbrev-ref", "HEAD").spm_chomp() + args: Git.tool, + "-C", + path.pathString, + "rev-parse", + "--abbrev-ref", + "HEAD" + ).spm_chomp() } /// Returns the revision for a given tag. func revision(forTag tag: String) throws -> String { return try AsyncProcess.checkNonZeroExit( - args: Git.tool, "-C", path.pathString, "rev-parse", tag).spm_chomp() + args: Git.tool, + "-C", + path.pathString, + "rev-parse", + tag + ).spm_chomp() } /// Stage a file. diff --git a/Sources/_InternalTestSupport/InMemoryGitRepository.swift b/Sources/_InternalTestSupport/InMemoryGitRepository.swift index cb8f5870534..5bf7bc931a1 100644 --- a/Sources/_InternalTestSupport/InMemoryGitRepository.swift +++ b/Sources/_InternalTestSupport/InMemoryGitRepository.swift @@ -96,7 +96,7 @@ public final class InMemoryGitRepository { } /// Copy/clone this repository. - fileprivate func copy(at newPath: AbsolutePath? = nil) throws -> InMemoryGitRepository { + fileprivate func copy(at newPath: AbsolutePath? = nil) throws -> InMemoryGitRepository { let path = newPath ?? self.path try self.fs.createDirectory(path, recursive: true) let repo = InMemoryGitRepository(path: path, fs: self.fs) diff --git a/Sources/_InternalTestSupport/MockBuildTestHelper.swift b/Sources/_InternalTestSupport/MockBuildTestHelper.swift index 024726107c9..eae91f9162e 100644 --- a/Sources/_InternalTestSupport/MockBuildTestHelper.swift +++ b/Sources/_InternalTestSupport/MockBuildTestHelper.swift @@ -21,11 +21,11 @@ import TSCUtility public struct MockToolchain: PackageModel.Toolchain { #if os(Windows) - public let librarianPath = AbsolutePath("/fake/path/to/link.exe") + public let librarianPath = AbsolutePath("/fake/path/to/link.exe") #elseif canImport(Darwin) - public let librarianPath = AbsolutePath("/fake/path/to/libtool") + public let librarianPath = AbsolutePath("/fake/path/to/libtool") #else - public let librarianPath = AbsolutePath("/fake/path/to/llvm-ar") + public let librarianPath = AbsolutePath("/fake/path/to/llvm-ar") #endif public let swiftCompilerPath = AbsolutePath("/fake/path/to/swiftc") public let includeSearchPaths = [AbsolutePath]() @@ -37,7 +37,8 @@ public struct MockToolchain: PackageModel.Toolchain { public let extraFlags = PackageModel.BuildFlags() public let installedSwiftPMConfiguration = InstalledSwiftPMConfiguration.default public let swiftPMLibrariesLocation = ToolchainConfiguration.SwiftPMLibrariesLocation( - manifestLibraryPath: AbsolutePath("/fake/manifestLib/path"), pluginLibraryPath: AbsolutePath("/fake/pluginLibrary/path") + manifestLibraryPath: AbsolutePath("/fake/manifestLib/path"), + pluginLibraryPath: AbsolutePath("/fake/pluginLibrary/path") ) public func getClangCompiler() throws -> AbsolutePath { @@ -46,9 +47,9 @@ public struct MockToolchain: PackageModel.Toolchain { public func _isClangCompilerVendorApple() throws -> Bool? { #if os(macOS) - return true + return true #else - return false + return false #endif } @@ -71,9 +72,9 @@ extension Basics.Triple { public let hostTriple = try! UserToolchain.default.targetTriple #if os(macOS) -public let defaultTargetTriple: String = hostTriple.tripleString(forPlatformVersion: "10.13") + public let defaultTargetTriple: String = hostTriple.tripleString(forPlatformVersion: "10.13") #else -public let defaultTargetTriple: String = hostTriple.tripleString + public let defaultTargetTriple: String = hostTriple.tripleString #endif public func mockBuildParameters( diff --git a/Sources/_InternalTestSupport/MockDependency.swift b/Sources/_InternalTestSupport/MockDependency.swift index 8e9f9f0dbef..3bc970eecb7 100644 --- a/Sources/_InternalTestSupport/MockDependency.swift +++ b/Sources/_InternalTestSupport/MockDependency.swift @@ -129,7 +129,7 @@ public struct MockDependency { ) } } - + } public static func fileSystem(path: String, products: ProductFilter = .everything, traits: Set = ["default"]) -> MockDependency { diff --git a/Sources/_InternalTestSupport/MockDependencyGraph.swift b/Sources/_InternalTestSupport/MockDependencyGraph.swift index b182e216bee..a1bb8e8c4ef 100644 --- a/Sources/_InternalTestSupport/MockDependencyGraph.swift +++ b/Sources/_InternalTestSupport/MockDependencyGraph.swift @@ -23,7 +23,7 @@ public struct MockDependencyGraph { public let containers: [MockPackageContainer] public let result: [PackageReference: Version] - public init(name: String, constraints: [MockPackageContainer.Constraint], containers: [MockPackageContainer], result: [PackageReference : Version]) { + public init(name: String, constraints: [MockPackageContainer.Constraint], containers: [MockPackageContainer], result: [PackageReference: Version]) { self.name = name self.constraints = constraints self.containers = containers diff --git a/Sources/_InternalTestSupport/MockHTTPClient.swift b/Sources/_InternalTestSupport/MockHTTPClient.swift index 1eb8cfa5792..596a742986b 100644 --- a/Sources/_InternalTestSupport/MockHTTPClient.swift +++ b/Sources/_InternalTestSupport/MockHTTPClient.swift @@ -16,7 +16,7 @@ extension HTTPClient { public static func mock(fileSystem: FileSystem) -> HTTPClient { HTTPClient { request, _ in switch request.kind { - case.generic: + case .generic: return .okay(body: request.url.absoluteString) case .download(let fileSystem, let destination): diff --git a/Sources/_InternalTestSupport/MockManifestLoader.swift b/Sources/_InternalTestSupport/MockManifestLoader.swift index 3ccfb3618cd..ef0c290c96d 100644 --- a/Sources/_InternalTestSupport/MockManifestLoader.swift +++ b/Sources/_InternalTestSupport/MockManifestLoader.swift @@ -84,7 +84,7 @@ extension ManifestLoader { dependencyMapper: DependencyMapper? = .none, fileSystem: FileSystem, observabilityScope: ObservabilityScope - ) async throws -> Manifest{ + ) async throws -> Manifest { let packageIdentity: PackageIdentity let packageLocation: String switch packageKind { diff --git a/Sources/_InternalTestSupport/MockPackage.swift b/Sources/_InternalTestSupport/MockPackage.swift index 1f0c62b1ba3..2bb4add6a2b 100644 --- a/Sources/_InternalTestSupport/MockPackage.swift +++ b/Sources/_InternalTestSupport/MockPackage.swift @@ -95,7 +95,7 @@ public struct MockPackage { self.platforms = platforms self.location = .registry( identity: .plain(identity), - alternativeURLs: alternativeURLs?.compactMap{ URL(string: $0) }, + alternativeURLs: alternativeURLs?.compactMap { URL(string: $0) }, metadata: metadata ) self.targets = targets @@ -111,10 +111,10 @@ public struct MockPackage { return MockPackage( name: name, targets: [ - try MockTarget(name: name), + try MockTarget(name: name) ], products: [ - MockProduct(name: name, modules: [name]), + MockProduct(name: name, modules: [name]) ], versions: ["1.0.0"] ) diff --git a/Sources/_InternalTestSupport/MockPackageFingerprintStorage.swift b/Sources/_InternalTestSupport/MockPackageFingerprintStorage.swift index 2d49aeab5d6..50ced189a13 100644 --- a/Sources/_InternalTestSupport/MockPackageFingerprintStorage.swift +++ b/Sources/_InternalTestSupport/MockPackageFingerprintStorage.swift @@ -19,13 +19,15 @@ import PackageModel import struct TSCUtility.Version public class MockPackageFingerprintStorage: PackageFingerprintStorage { - private var packageFingerprints: [PackageIdentity: [Version: [Fingerprint + private var packageFingerprints: + [PackageIdentity: [Version: [Fingerprint .Kind: [Fingerprint.ContentType: Fingerprint]]]] private let lock = NSLock() - public init(_ packageFingerprints: [PackageIdentity: [Version: [Fingerprint - .Kind: [Fingerprint.ContentType: Fingerprint]]]] = [:]) - { + public init( + _ packageFingerprints: [PackageIdentity: [Version: [Fingerprint + .Kind: [Fingerprint.ContentType: Fingerprint]]]] = [:] + ) { self.packageFingerprints = packageFingerprints } diff --git a/Sources/_InternalTestSupport/MockPackageGraphs.swift b/Sources/_InternalTestSupport/MockPackageGraphs.swift index 1516d517a1a..96421985cbc 100644 --- a/Sources/_InternalTestSupport/MockPackageGraphs.swift +++ b/Sources/_InternalTestSupport/MockPackageGraphs.swift @@ -17,8 +17,7 @@ import class Basics.ObservabilityScope import struct PackageGraph.ModulesGraph -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import func PackageGraph.loadModulesGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import func PackageGraph.loadModulesGraph import class PackageModel.Manifest import struct PackageModel.ProductDescription @@ -33,8 +32,9 @@ package typealias MockPackageGraph = ( ) package func macrosPackageGraph() throws -> MockPackageGraph { - let fs = InMemoryFileSystem(emptyFiles: - "/swift-firmware/Sources/Core/source.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/swift-firmware/Sources/Core/source.swift", "/swift-firmware/Sources/HAL/source.swift", "/swift-firmware/Tests/CoreTests/source.swift", "/swift-firmware/Tests/HALTests/source.swift", @@ -104,7 +104,7 @@ package func macrosPackageGraph() throws -> MockPackageGraph { name: "MMIOMacros", dependencies: [.product(name: "SwiftSyntax", package: "swift-syntax")], type: .macro - ) + ), ], traits: [] ), @@ -136,8 +136,9 @@ package func macrosPackageGraph() throws -> MockPackageGraph { } package func macrosTestsPackageGraph() throws -> MockPackageGraph { - let fs = InMemoryFileSystem(emptyFiles: - "/swift-mmio/Plugins/MMIOPlugin/source.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/swift-mmio/Plugins/MMIOPlugin/source.swift", "/swift-mmio/Sources/MMIO/source.swift", "/swift-mmio/Sources/MMIOMacros/source.swift", "/swift-mmio/Sources/MMIOMacrosTests/source.swift", @@ -174,7 +175,7 @@ package func macrosTestsPackageGraph() throws -> MockPackageGraph { name: "MMIOPlugin", type: .plugin, targets: ["MMIOPlugin"] - ) + ), ], targets: [ TargetDescription( @@ -198,7 +199,7 @@ package func macrosTestsPackageGraph() throws -> MockPackageGraph { name: "MMIOMacrosTests", dependencies: [ .target(name: "MMIOMacros"), - .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax") + .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), ], type: .test ), @@ -206,7 +207,7 @@ package func macrosTestsPackageGraph() throws -> MockPackageGraph { name: "MMIOMacro+PluginTests", dependencies: [ .target(name: "MMIOPlugin"), - .target(name: "MMIOMacros") + .target(name: "MMIOMacros"), ], type: .test ), @@ -214,7 +215,7 @@ package func macrosTestsPackageGraph() throws -> MockPackageGraph { name: "NOOPTests", dependencies: [], type: .test - ) + ), ], traits: [] ), @@ -297,7 +298,7 @@ package func macrosTestsPackageGraph() throws -> MockPackageGraph { package func trivialPackageGraph() throws -> MockPackageGraph { let fs = InMemoryFileSystem( emptyFiles: - "/Pkg/Sources/app/main.swift", + "/Pkg/Sources/app/main.swift", "/Pkg/Sources/lib/lib.c", "/Pkg/Sources/lib/include/lib.h", "/Pkg/Tests/test/TestCase.swift" @@ -316,7 +317,7 @@ package func trivialPackageGraph() throws -> MockPackageGraph { TargetDescription(name: "test", dependencies: ["lib"], type: .test), ], traits: [] - ), + ) ], observabilityScope: observability.topScope, traitConfiguration: .default, @@ -330,7 +331,7 @@ package func trivialPackageGraph() throws -> MockPackageGraph { package func embeddedCxxInteropPackageGraph() throws -> MockPackageGraph { let fs = InMemoryFileSystem( emptyFiles: - "/Pkg/Sources/app/main.swift", + "/Pkg/Sources/app/main.swift", "/Pkg/Sources/lib/lib.cpp", "/Pkg/Sources/lib/include/lib.h", "/Pkg/Tests/test/TestCase.swift" @@ -361,7 +362,7 @@ package func embeddedCxxInteropPackageGraph() throws -> MockPackageGraph { ), ], traits: [] - ), + ) ], observabilityScope: observability.topScope, traitConfiguration: .default, @@ -373,8 +374,9 @@ package func embeddedCxxInteropPackageGraph() throws -> MockPackageGraph { } package func toolsExplicitLibrariesGraph(linkage: ProductType.LibraryType) throws -> MockPackageGraph { - let fs = InMemoryFileSystem(emptyFiles: - "/swift-mmio/Sources/MMIOMacros/source.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/swift-mmio/Sources/MMIOMacros/source.swift", "/swift-mmio/Sources/MMIOMacrosTests/source.swift", "/swift-syntax/Sources/SwiftSyntax/source.swift" ) @@ -396,17 +398,17 @@ package func toolsExplicitLibrariesGraph(linkage: ProductType.LibraryType) throw TargetDescription( name: "MMIOMacros", dependencies: [ - .product(name: "SwiftSyntax", package: "swift-syntax"), + .product(name: "SwiftSyntax", package: "swift-syntax") ], type: .macro ), TargetDescription( name: "MMIOMacrosTests", dependencies: [ - .target(name: "MMIOMacros"), + .target(name: "MMIOMacros") ], type: .test - ) + ), ], traits: [] ), @@ -418,13 +420,13 @@ package func toolsExplicitLibrariesGraph(linkage: ProductType.LibraryType) throw name: "SwiftSyntax", type: .library(linkage), targets: ["SwiftSyntax"] - ), + ) ], targets: [ TargetDescription( name: "SwiftSyntax", dependencies: [] - ), + ) ], traits: [] ), diff --git a/Sources/_InternalTestSupport/MockPackageSigningEntityStorage.swift b/Sources/_InternalTestSupport/MockPackageSigningEntityStorage.swift index e3177b3e0fc..436027a4112 100644 --- a/Sources/_InternalTestSupport/MockPackageSigningEntityStorage.swift +++ b/Sources/_InternalTestSupport/MockPackageSigningEntityStorage.swift @@ -26,7 +26,7 @@ public class MockPackageSigningEntityStorage: PackageSigningEntityStorage { public init(_ packageSigners: [PackageIdentity: PackageSigners] = [:]) { self.packageSigners = packageSigners } - + public func get( package: PackageIdentity, observabilityScope: ObservabilityScope @@ -45,7 +45,8 @@ public class MockPackageSigningEntityStorage: PackageSigningEntityStorage { observabilityScope: ObservabilityScope ) throws { try self.lock.withLock { - let otherSigningEntities = self.packageSigners[package]?.signingEntities(of: version) + let otherSigningEntities = + self.packageSigners[package]?.signingEntities(of: version) .filter { $0 != signingEntity } ?? [] // Error if we try to write a different signing entity for a version guard otherSigningEntities.isEmpty else { @@ -53,7 +54,7 @@ public class MockPackageSigningEntityStorage: PackageSigningEntityStorage { package: package, version: version, given: signingEntity, - existing: otherSigningEntities.first! // !-safe because otherSigningEntities is not empty + existing: otherSigningEntities.first! // !-safe because otherSigningEntities is not empty ) } diff --git a/Sources/_InternalTestSupport/MockRegistry.swift b/Sources/_InternalTestSupport/MockRegistry.swift index cee1ba0cc06..c1847082a93 100644 --- a/Sources/_InternalTestSupport/MockRegistry.swift +++ b/Sources/_InternalTestSupport/MockRegistry.swift @@ -153,11 +153,11 @@ public class MockRegistry { let package = PackageIdentity.plain(routeComponents.joined(separator: ".")) return try self.getPackageMetadata(packageIdentity: package) case 3: - let package = PackageIdentity.plain(routeComponents[0 ... 1].joined(separator: ".")) + let package = PackageIdentity.plain(routeComponents[0...1].joined(separator: ".")) let version = String(routeComponents[2]) return try self.getVersionMetadata(packageIdentity: package, version: version) case 4 where routeComponents[3] == "Package.swift": - let package = PackageIdentity.plain(routeComponents[0 ... 1].joined(separator: ".")) + let package = PackageIdentity.plain(routeComponents[0...1].joined(separator: ".")) let version = String(routeComponents[2]) guard let components = URLComponents(url: request.url, resolvingAgainstBaseURL: false) else { throw StringError("invalid url: \(request.url)") @@ -230,7 +230,7 @@ public class MockRegistry { type: "application/zip", checksum: zipfileChecksum.hexadecimalRepresentation, signing: nil - ), + ) ], metadata: .init( description: "\(packageIdentity) description", @@ -309,7 +309,7 @@ public class MockRegistry { throw StringError("invalid request \(request.url), expecting zip suffix") } - let packageIdentity = PackageIdentity.plain(routeComponents[0 ... 1].joined(separator: ".")) + let packageIdentity = PackageIdentity.plain(routeComponents[0...1].joined(separator: ".")) let version = String(routeComponents[2].dropLast(4)) guard let package = self.packageVersions[packageIdentity]?[version] else { @@ -409,7 +409,7 @@ private struct MockRegistryArchiver: Archiver { throw StringError("invalid mock zip format, not enough lines") } let rootPath = lines[1] - for path in lines[2 ..< lines.count] { + for path in lines[2.. Void ) async throws { - let dependencies = try deps.map { try $0.convert( - baseURL: self.packagesDir, - identityResolver: self.identityResolver - ) } + let dependencies = try deps.map { + try $0.convert( + baseURL: self.packagesDir, + identityResolver: self.identityResolver + ) + } let observability = ObservabilitySystem.makeForTesting() await observability.topScope.trap { @@ -571,10 +582,12 @@ public final class MockWorkspace { deps: [MockDependency] = [], _ result: ([(PackageReference, Workspace.PackageStateChange)]?, [Basics.Diagnostic]) -> Void ) async throws { - let dependencies = try deps.map { try $0.convert( - baseURL: self.packagesDir, - identityResolver: self.identityResolver - ) } + let dependencies = try deps.map { + try $0.convert( + baseURL: self.packagesDir, + identityResolver: self.identityResolver + ) + } let rootInput = try PackageGraphRootInput( packages: rootPaths(for: roots), dependencies: dependencies, @@ -582,14 +595,15 @@ public final class MockWorkspace { ) let observability = ObservabilitySystem.makeForTesting() - let changes = await observability.topScope.trap { () -> [(PackageReference, Workspace.PackageStateChange)]? in - let workspace = try self.getOrCreateWorkspace() - return try await workspace.updateDependencies( - root: rootInput, - dryRun: true, - observabilityScope: observability.topScope - ) - } ?? nil + let changes = + await observability.topScope.trap { () -> [(PackageReference, Workspace.PackageStateChange)]? in + let workspace = try self.getOrCreateWorkspace() + return try await workspace.updateDependencies( + root: rootInput, + dryRun: true, + observabilityScope: observability.topScope + ) + } ?? nil result(changes, observability.diagnostics) } @@ -598,10 +612,12 @@ public final class MockWorkspace { deps: [MockDependency], _ result: (ModulesGraph, [Basics.Diagnostic]) throws -> Void ) async throws { - let dependencies = try deps.map { try $0.convert( - baseURL: self.packagesDir, - identityResolver: self.identityResolver - ) } + let dependencies = try deps.map { + try $0.convert( + baseURL: self.packagesDir, + identityResolver: self.identityResolver + ) + } try await self.checkPackageGraph(roots: roots, dependencies: dependencies, result) } @@ -614,7 +630,9 @@ public final class MockWorkspace { ) async throws { let observability = ObservabilitySystem.makeForTesting() let rootInput = try PackageGraphRootInput( - packages: rootPaths(for: roots), dependencies: dependencies, traitConfiguration: traitConfiguration + packages: rootPaths(for: roots), + dependencies: dependencies, + traitConfiguration: traitConfiguration ) let workspace = try self.getOrCreateWorkspace() do { @@ -639,10 +657,12 @@ public final class MockWorkspace { deps: [MockDependency], _ result: ([Basics.Diagnostic]) -> Void ) async throws { - let dependencies = try deps.map { try $0.convert( - baseURL: self.packagesDir, - identityResolver: self.identityResolver - ) } + let dependencies = try deps.map { + try $0.convert( + baseURL: self.packagesDir, + identityResolver: self.identityResolver + ) + } await self.checkPackageGraphFailure(roots: roots, dependencies: dependencies, result) } @@ -944,13 +964,17 @@ public final class MockWorkspace { _ result: (Workspace.DependencyManifests, [Basics.Diagnostic]) -> Void ) async throws { let observability = ObservabilitySystem.makeForTesting() - let dependencies = try deps.map { try $0.convert( - baseURL: self.packagesDir, - identityResolver: self.identityResolver - ) } + let dependencies = try deps.map { + try $0.convert( + baseURL: self.packagesDir, + identityResolver: self.identityResolver + ) + } let workspace = try self.getOrCreateWorkspace() let rootInput = try PackageGraphRootInput( - packages: rootPaths(for: roots), dependencies: dependencies, traitConfiguration: traitConfiguration + packages: rootPaths(for: roots), + dependencies: dependencies, + traitConfiguration: traitConfiguration ) let rootManifests = try await workspace.loadRootManifests( packages: rootInput.packages, diff --git a/Sources/_InternalTestSupport/Observability.swift b/Sources/_InternalTestSupport/Observability.swift index 2d934abf8dc..4c1f4d82d15 100644 --- a/Sources/_InternalTestSupport/Observability.swift +++ b/Sources/_InternalTestSupport/Observability.swift @@ -98,7 +98,7 @@ public func XCTAssertNoDiagnostics( ) { let diagnostics = problemsOnly ? diagnostics.filter { $0.severity >= .warning } : diagnostics if diagnostics.isEmpty { return } - + let description = diagnostics.map { "- " + $0.description }.joined(separator: "\n") XCTFail("Found unexpected diagnostics: \n\(description)", file: file, line: line) } @@ -166,7 +166,6 @@ public func expectDiagnostics( ) } - public func expectDiagnostics( _ diagnostics: [Basics.Diagnostic], minSeverity: Basics.Diagnostic.Severity, @@ -180,9 +179,9 @@ public func expectDiagnostics( if !testResult.uncheckedDiagnostics.isEmpty { Issue.record("unchecked diagnostics \(testResult.uncheckedDiagnostics)", sourceLocation: sourceLocation) - } + } } - + public func testPartialDiagnostics( _ diagnostics: [Basics.Diagnostic], minSeverity: Basics.Diagnostic.Severity, @@ -265,9 +264,9 @@ public class DiagnosticsTestResult { //XCTAssertEqual(diagnostic.metadata?.droppingLegacyKeys(), metadata?.droppingLegacyKeys(), file: file, line: line) self.uncheckedDiagnostics.remove(at: index) return diagnostic - // FIXME: (diagnostics) compare complete metadata when legacy bridge is removed - } else if let index = self.uncheckedDiagnostics.firstIndex(where: { diagnostic in diagnostic.severity == severity /*&& diagnostic.metadata == metadata*/}) { - //} else if let index = self.uncheckedDiagnostics.firstIndex(where: { diagnostic in diagnostic.severity == severity && diagnostic.metadata?.droppingLegacyKeys() == metadata?.droppingLegacyKeys()}) { + // FIXME: (diagnostics) compare complete metadata when legacy bridge is removed + } else if let index = self.uncheckedDiagnostics.firstIndex(where: { diagnostic in diagnostic.severity == severity /*&& diagnostic.metadata == metadata*/ }) { + //} else if let index = self.uncheckedDiagnostics.firstIndex(where: { diagnostic in diagnostic.severity == severity && diagnostic.metadata?.droppingLegacyKeys() == metadata?.droppingLegacyKeys()}) { let diagnostic = self.uncheckedDiagnostics[index] self.uncheckedDiagnostics.remove(at: index) return diagnostic diff --git a/Sources/_InternalTestSupport/PackageGraphTester.swift b/Sources/_InternalTestSupport/PackageGraphTester.swift index fb9a46ea381..c733fa89cc3 100644 --- a/Sources/_InternalTestSupport/PackageGraphTester.swift +++ b/Sources/_InternalTestSupport/PackageGraphTester.swift @@ -29,11 +29,11 @@ public final class PackageGraphResult { } public func check(roots: PackageIdentity..., sourceLocation: SourceLocation = #_sourceLocation) { - #expect(graph.rootPackages.map{$0.identity }.sorted() == roots.sorted(), sourceLocation: sourceLocation) + #expect(graph.rootPackages.map { $0.identity }.sorted() == roots.sorted(), sourceLocation: sourceLocation) } public func check(packages: PackageIdentity..., sourceLocation: SourceLocation = #_sourceLocation) { - #expect(graph.packages.map {$0.identity }.sorted() == packages.sorted(), sourceLocation: sourceLocation) + #expect(graph.packages.map { $0.identity }.sorted() == packages.sorted(), sourceLocation: sourceLocation) } public func check(modules: String..., sourceLocation: SourceLocation = #_sourceLocation) { @@ -41,7 +41,9 @@ public final class PackageGraphResult { graph.allModules .filter { $0.type != .test } .map { $0.name } - .sorted() == modules.sorted(), sourceLocation: sourceLocation) + .sorted() == modules.sorted(), + sourceLocation: sourceLocation + ) } public func check(products: String..., sourceLocation: SourceLocation = #_sourceLocation) { @@ -99,7 +101,6 @@ public final class PackageGraphResult { ) throws { let product = try #require(graph.product(for: name), "Product \(name) not found", sourceLocation: sourceLocation) - body(ResolvedProductResult(product)) } @@ -115,9 +116,11 @@ public final class PackageGraphResult { public func check(testModules: String..., sourceLocation: SourceLocation = #_sourceLocation) { #expect( graph.allModules - .filter{ $0.type == .test } - .map{ $0.name } - .sorted() == testModules.sorted(), sourceLocation: sourceLocation) + .filter { $0.type == .test } + .map { $0.name } + .sorted() == testModules.sorted(), + sourceLocation: sourceLocation + ) } public func find(package: PackageIdentity) -> ResolvedPackage? { @@ -126,7 +129,8 @@ public final class PackageGraphResult { private func reachableBuildTargets(in environment: BuildEnvironment) throws -> IdentifiableSet { let inputTargets = graph.inputPackages.lazy.flatMap { $0.modules } - let recursiveBuildTargetDependencies = try inputTargets + let recursiveBuildTargetDependencies = + try inputTargets .flatMap { try $0.recursiveDependencies(satisfying: environment) } .compactMap { $0.module } return IdentifiableSet(inputTargets).union(recursiveBuildTargetDependencies) @@ -183,7 +187,9 @@ public final class ResolvedTargetResult { public func checkDerivedPlatforms(_ platforms: [String: String], sourceLocation: SourceLocation = #_sourceLocation) { let derived = platforms.map { - let platform = PlatformRegistry.default.platformByName[$0.key] ?? PackageModel.Platform + let platform = + PlatformRegistry.default.platformByName[$0.key] + ?? PackageModel.Platform .custom(name: $0.key, oldestSupportedVersion: $0.value) return self.target.getSupportedPlatform(for: platform, usingXCTest: self.target.type == .test) } @@ -248,8 +254,8 @@ public final class ResolvedTargetDependencyResult { body: (ResolvedProductResult) -> Void ) { guard case let .product(product, _) = self.dependency else { - Issue.record("Dependency \(dependency) is not a product", sourceLocation: sourceLocation) - return + Issue.record("Dependency \(dependency) is not a product", sourceLocation: sourceLocation) + return } body(ResolvedProductResult(product)) } diff --git a/Sources/_InternalTestSupport/PackageGraphTesterXCTest.swift b/Sources/_InternalTestSupport/PackageGraphTesterXCTest.swift index d2be6488fb6..40838ff7d48 100644 --- a/Sources/_InternalTestSupport/PackageGraphTesterXCTest.swift +++ b/Sources/_InternalTestSupport/PackageGraphTesterXCTest.swift @@ -31,11 +31,11 @@ public final class PackageGraphResultXCTest { } public func check(roots: PackageIdentity..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(graph.rootPackages.map{$0.identity }.sorted(), roots.sorted(), file: file, line: line) + XCTAssertEqual(graph.rootPackages.map { $0.identity }.sorted(), roots.sorted(), file: file, line: line) } public func check(packages: PackageIdentity..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(graph.packages.map {$0.identity }.sorted(), packages.sorted(), file: file, line: line) + XCTAssertEqual(graph.packages.map { $0.identity }.sorted(), packages.sorted(), file: file, line: line) } public func check(modules: String..., file: StaticString = #file, line: UInt = #line) { @@ -43,7 +43,11 @@ public final class PackageGraphResultXCTest { graph.allModules .filter { $0.type != .test } .map { $0.name } - .sorted(), modules.sorted(), file: file, line: line) + .sorted(), + modules.sorted(), + file: file, + line: line + ) } public func check(products: String..., file: StaticString = #file, line: UInt = #line) { @@ -132,9 +136,13 @@ public final class PackageGraphResultXCTest { public func check(testModules: String..., file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( graph.allModules - .filter{ $0.type == .test } - .map{ $0.name } - .sorted(), testModules.sorted(), file: file, line: line) + .filter { $0.type == .test } + .map { $0.name } + .sorted(), + testModules.sorted(), + file: file, + line: line + ) } public func find(package: PackageIdentity) -> ResolvedPackage? { @@ -143,7 +151,8 @@ public final class PackageGraphResultXCTest { private func reachableBuildTargets(in environment: BuildEnvironment) throws -> IdentifiableSet { let inputTargets = graph.inputPackages.lazy.flatMap { $0.modules } - let recursiveBuildTargetDependencies = try inputTargets + let recursiveBuildTargetDependencies = + try inputTargets .flatMap { try $0.recursiveDependencies(satisfying: environment) } .compactMap { $0.module } return IdentifiableSet(inputTargets).union(recursiveBuildTargetDependencies) @@ -200,7 +209,9 @@ public final class ResolvedTargetResultXCTest { public func checkDerivedPlatforms(_ platforms: [String: String], file: StaticString = #file, line: UInt = #line) { let derived = platforms.map { - let platform = PlatformRegistry.default.platformByName[$0.key] ?? PackageModel.Platform + let platform = + PlatformRegistry.default.platformByName[$0.key] + ?? PackageModel.Platform .custom(name: $0.key, oldestSupportedVersion: $0.value) return self.target.getSupportedPlatform(for: platform, usingXCTest: self.target.type == .test) } diff --git a/Sources/_InternalTestSupport/ProcessInfo+hostutils.swift b/Sources/_InternalTestSupport/ProcessInfo+hostutils.swift index c09a1c59812..a874b5cf955 100644 --- a/Sources/_InternalTestSupport/ProcessInfo+hostutils.swift +++ b/Sources/_InternalTestSupport/ProcessInfo+hostutils.swift @@ -26,4 +26,4 @@ extension ProcessInfo { return contentString.contains(al2_name) } -} \ No newline at end of file +} diff --git a/Sources/_InternalTestSupport/ResolvedModule+Mock.swift b/Sources/_InternalTestSupport/ResolvedModule+Mock.swift index aa2818d49e0..4e892c8bb24 100644 --- a/Sources/_InternalTestSupport/ResolvedModule+Mock.swift +++ b/Sources/_InternalTestSupport/ResolvedModule+Mock.swift @@ -39,4 +39,3 @@ extension ResolvedModule { ) } } - diff --git a/Sources/_InternalTestSupport/SwiftPMProduct.swift b/Sources/_InternalTestSupport/SwiftPMProduct.swift index 86422039ebc..5b341068287 100644 --- a/Sources/_InternalTestSupport/SwiftPMProduct.swift +++ b/Sources/_InternalTestSupport/SwiftPMProduct.swift @@ -121,17 +121,17 @@ extension SwiftPM { env: Environment? = nil ) async throws -> AsyncProcessResult { var environment = Environment.current -#if !os(Windows) - environment["SDKROOT"] = nil -#endif - -#if Xcode - // Unset these variables which causes issues when running tests via Xcode. - environment["XCTestConfigurationFilePath"] = nil - environment["XCTestSessionIdentifier"] = nil - environment["XCTestBundlePath"] = nil - environment["NSUnbufferedIO"] = nil -#endif + #if !os(Windows) + environment["SDKROOT"] = nil + #endif + + #if Xcode + // Unset these variables which causes issues when running tests via Xcode. + environment["XCTestConfigurationFilePath"] = nil + environment["XCTestSessionIdentifier"] = nil + environment["XCTestBundlePath"] = nil + environment["NSUnbufferedIO"] = nil + #endif // FIXME: We use this private environment variable hack to be able to // create special conditions in swift-build for swiftpm tests. environment["SWIFTPM_TESTS_MODULECACHE"] = self.xctestBinaryPath.parentDirectory.pathString diff --git a/Sources/_InternalTestSupport/SwiftTesting+Helpers.swift b/Sources/_InternalTestSupport/SwiftTesting+Helpers.swift index d7e3185b9a4..112c92b4cd4 100644 --- a/Sources/_InternalTestSupport/SwiftTesting+Helpers.swift +++ b/Sources/_InternalTestSupport/SwiftTesting+Helpers.swift @@ -81,7 +81,7 @@ public func expectDirectoryExists( at path: AbsolutePath, sourceLocation: SourceLocation = #_sourceLocation, ) { -let msgSuffix: String + let msgSuffix: String do { msgSuffix = try "Directory contents: \(localFileSystem.getDirectoryContents(path))" } catch { @@ -146,7 +146,7 @@ public func expectThrowsCommandExecutionError( } private func _expectThrowsCommandExecutionError( - _ expressionClosure: @autoclosure () async throws -> T, + _ expressionClosure: @autoclosure () async throws -> T, _ message: @autoclosure () -> Comment, _ sourceLocation: SourceLocation, _ errorHandler: (_ error: CommandExecutionError) throws -> R @@ -164,9 +164,10 @@ private func _expectThrowsCommandExecutionError( } guard let error = err, - case .executionFailure(let processError, let stdout, let stderr) = error, - case AsyncProcessResult.Error.nonZeroExit(let processResult) = processError, - processResult.exitStatus != .terminated(code: 0) else { + case .executionFailure(let processError, let stdout, let stderr) = error, + case AsyncProcessResult.Error.nonZeroExit(let processResult) = processError, + processResult.exitStatus != .terminated(code: 0) + else { Issue.record("Unexpected error type: \(err?.interpolationDescription ?? "")", sourceLocation: sourceLocation) return Optional.none } diff --git a/Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift b/Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift index a08104d793a..c8e7a0fc5a1 100644 --- a/Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift +++ b/Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift @@ -76,7 +76,7 @@ extension Trait where Self == Testing.Bug { ) } - public static var IssueLdFailsUnexpectedly : Self { + public static var IssueLdFailsUnexpectedly: Self { .issue( "https://github.com/swiftlang/swift-package-manager/issues/9249", relationship: .defect, diff --git a/Sources/_InternalTestSupport/Toolchain.swift b/Sources/_InternalTestSupport/Toolchain.swift index 3bbb62cb620..bafff568d5f 100644 --- a/Sources/_InternalTestSupport/Toolchain.swift +++ b/Sources/_InternalTestSupport/Toolchain.swift @@ -21,24 +21,24 @@ import struct TSCBasic.StringError import struct TSCUtility.SerializedDiagnostics #if os(macOS) -package func macOSBundleRoot() throws -> AbsolutePath { - for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") { - return try AbsolutePath(validating: bundle.bundlePath).parentDirectory - } - if let testBundlePath = nextItem(in: ProcessInfo.processInfo.arguments, after: "--test-bundle-path") { - let binDir = AbsolutePath(testBundlePath).parentDirectory.parentDirectory.parentDirectory.parentDirectory - return binDir + package func macOSBundleRoot() throws -> AbsolutePath { + for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") { + return try AbsolutePath(validating: bundle.bundlePath).parentDirectory + } + if let testBundlePath = nextItem(in: ProcessInfo.processInfo.arguments, after: "--test-bundle-path") { + let binDir = AbsolutePath(testBundlePath).parentDirectory.parentDirectory.parentDirectory.parentDirectory + return binDir + } + fatalError("Unable to find macOS bundle root") } - fatalError("Unable to find macOS bundle root") -} #endif package func resolveBinDir() throws -> AbsolutePath { -#if os(macOS) - return try macOSBundleRoot() -#else - return try AbsolutePath(validating: CommandLine.arguments[0], relativeTo: localFileSystem.currentWorkingDirectory!).parentDirectory -#endif + #if os(macOS) + return try macOSBundleRoot() + #else + return try AbsolutePath(validating: CommandLine.arguments[0], relativeTo: localFileSystem.currentWorkingDirectory!).parentDirectory + #endif } extension SwiftSDK { @@ -61,34 +61,33 @@ extension UserToolchain { extension UserToolchain { /// Helper function to determine if async await actually works in the current environment. public func supportsSwiftConcurrency() -> Bool { - #if os(macOS) - if #available(macOS 12.0, *) { - // On macOS 12 and later, concurrency is assumed to work. - return true - } - else { - // On macOS 11 and earlier, we don't know if concurrency actually works because not all SDKs and toolchains have the right bits. We could examine the SDK and the various libraries, but the most accurate test is to just try to compile and run a snippet of code that requires async/await support. It doesn't have to actually do anything, it's enough that all the libraries can be found (but because the library reference is weak we do need the linkage reference to `_swift_task_create` and the like). - do { - try testWithTemporaryDirectory { tmpPath in - let inputPath = tmpPath.appending("foo.swift") - try localFileSystem.writeFileContents(inputPath, string: "public func foo() async {}\nTask { await foo() }") - let outputPath = tmpPath.appending("foo") - let toolchainPath = self.swiftCompilerPath.parentDirectory.parentDirectory - let backDeploymentLibPath = toolchainPath.appending(components: "lib", "swift-5.5", "macosx") - try AsyncProcess.checkNonZeroExit(arguments: ["/usr/bin/xcrun", "--toolchain", toolchainPath.pathString, "swiftc", inputPath.pathString, "-Xlinker", "-rpath", "-Xlinker", backDeploymentLibPath.pathString, "-o", outputPath.pathString]) - try AsyncProcess.checkNonZeroExit(arguments: [outputPath.pathString]) + #if os(macOS) + if #available(macOS 12.0, *) { + // On macOS 12 and later, concurrency is assumed to work. + return true + } else { + // On macOS 11 and earlier, we don't know if concurrency actually works because not all SDKs and toolchains have the right bits. We could examine the SDK and the various libraries, but the most accurate test is to just try to compile and run a snippet of code that requires async/await support. It doesn't have to actually do anything, it's enough that all the libraries can be found (but because the library reference is weak we do need the linkage reference to `_swift_task_create` and the like). + do { + try testWithTemporaryDirectory { tmpPath in + let inputPath = tmpPath.appending("foo.swift") + try localFileSystem.writeFileContents(inputPath, string: "public func foo() async {}\nTask { await foo() }") + let outputPath = tmpPath.appending("foo") + let toolchainPath = self.swiftCompilerPath.parentDirectory.parentDirectory + let backDeploymentLibPath = toolchainPath.appending(components: "lib", "swift-5.5", "macosx") + try AsyncProcess.checkNonZeroExit(arguments: ["/usr/bin/xcrun", "--toolchain", toolchainPath.pathString, "swiftc", inputPath.pathString, "-Xlinker", "-rpath", "-Xlinker", backDeploymentLibPath.pathString, "-o", outputPath.pathString]) + try AsyncProcess.checkNonZeroExit(arguments: [outputPath.pathString]) + } + } catch { + // On any failure we assume false. + return false } - } catch { - // On any failure we assume false. - return false + // If we get this far we could compile and run a trivial executable that uses libConcurrency, so we can say that this toolchain supports concurrency on this host. + return true } - // If we get this far we could compile and run a trivial executable that uses libConcurrency, so we can say that this toolchain supports concurrency on this host. + #else + // On other platforms, concurrency is assumed to work since with new enough versions of the toolchain. return true - } - #else - // On other platforms, concurrency is assumed to work since with new enough versions of the toolchain. - return true - #endif + #endif } /// Helper function to determine whether serialized diagnostics work properly in the current environment. @@ -108,7 +107,7 @@ extension UserToolchain { "-Xfrontend", "-serialize-diagnostics-path", "-Xfrontend", serializedDiagnosticsPath.pathString, "-g", - "-o", outputPath.pathString + "-o", outputPath.pathString, ] + otherSwiftFlags ) try AsyncProcess.checkNonZeroExit(arguments: [outputPath.pathString]) diff --git a/Sources/_InternalTestSupport/XCTAssertHelpers.swift b/Sources/_InternalTestSupport/XCTAssertHelpers.swift index 8c83236889f..8ba90f1fb73 100644 --- a/Sources/_InternalTestSupport/XCTAssertHelpers.swift +++ b/Sources/_InternalTestSupport/XCTAssertHelpers.swift @@ -13,7 +13,7 @@ import class Foundation.ProcessInfo import Basics #if os(macOS) -import class Foundation.Bundle + import class Foundation.Bundle #endif import SPMBuildCore import enum PackageModel.BuildConfiguration @@ -51,8 +51,7 @@ public func XCTAssertNoSuchPath(_ path: AbsolutePath, file: StaticString = #file swiftTestingTestCalledAnXCTestAPI() } - -public func XCTAssertEqual (_ lhs:(T,U), _ rhs:(T,U), file: StaticString = #file, line: UInt = #line) { +public func XCTAssertEqual(_ lhs: (T, U), _ rhs: (T, U), file: StaticString = #file, line: UInt = #line) { TSCTestSupport.XCTAssertEqual(lhs, rhs, file: file, line: line) swiftTestingTestCalledAnXCTestAPI() } @@ -74,26 +73,26 @@ public func XCTSkipIfselfHostedCI(because reason: String, file: StaticString = # swiftTestingTestCalledAnXCTestAPI() } -public func XCTSkipOnWindows(because reason: String? = nil, skipPlatformCi: Bool = false, skipSelfHostedCI: Bool = false , file: StaticString = #filePath, line: UInt = #line) throws { +public func XCTSkipOnWindows(because reason: String? = nil, skipPlatformCi: Bool = false, skipSelfHostedCI: Bool = false, file: StaticString = #filePath, line: UInt = #line) throws { swiftTestingTestCalledAnXCTestAPI() #if os(Windows) - let failureCause: String - if let reason { - failureCause = " because \(reason.description)" - } else { - failureCause = "" - } - if (skipPlatformCi) { - try XCTSkipIfPlatformCI(because: "Test is run in Platform CI. Skipping\(failureCause)", file: file, line: line) - } + let failureCause: String + if let reason { + failureCause = " because \(reason.description)" + } else { + failureCause = "" + } + if (skipPlatformCi) { + try XCTSkipIfPlatformCI(because: "Test is run in Platform CI. Skipping\(failureCause)", file: file, line: line) + } - if (skipSelfHostedCI) { - try XCTSkipIfselfHostedCI(because: "Test is run in Self hosted CI. Skipping\(failureCause)", file: file, line: line) - } + if (skipSelfHostedCI) { + try XCTSkipIfselfHostedCI(because: "Test is run in Self hosted CI. Skipping\(failureCause)", file: file, line: line) + } - if (!skipPlatformCi && !skipSelfHostedCI) { - throw XCTSkip("Skipping test\(failureCause)", file: file, line: line) - } + if (!skipPlatformCi && !skipSelfHostedCI) { + throw XCTSkip("Skipping test\(failureCause)", file: file, line: line) + } #endif } @@ -119,7 +118,8 @@ public func XCTRequires( try _requiresTools(executable) } catch (let AsyncProcessResult.Error.nonZeroExit(result)) { throw XCTSkip( - "Skipping as tool \(executable) is not found in the path. (\(result.description))") + "Skipping as tool \(executable) is not found in the path. (\(result.description))" + ) } } @@ -316,8 +316,9 @@ public func XCTAssertThrowsCommandExecutionError( swiftTestingTestCalledAnXCTestAPI() await XCTAssertAsyncThrowsError(try await expression(), message(), file: file, line: line) { error in guard case SwiftPMError.executionFailure(let processError, let stdout, let stderr) = error, - case AsyncProcessResult.Error.nonZeroExit(let processResult) = processError, - processResult.exitStatus != .terminated(code: 0) else { + case AsyncProcessResult.Error.nonZeroExit(let processResult) = processError, + processResult.exitStatus != .terminated(code: 0) + else { return XCTFail("Unexpected error type: \(error.interpolationDescription)", file: file, line: line) } errorHandler(CommandExecutionError(result: processResult, stdout: stdout, stderr: stderr)) @@ -354,7 +355,6 @@ public func XCTAsyncUnwrap( return result } - public struct CommandExecutionError: Error { package let result: AsyncProcessResult public let stdout: String diff --git a/Sources/_InternalTestSupport/misc.swift b/Sources/_InternalTestSupport/misc.swift index e659cf71c0a..7585a538946 100644 --- a/Sources/_InternalTestSupport/misc.swift +++ b/Sources/_InternalTestSupport/misc.swift @@ -14,12 +14,11 @@ import Foundation import Basics import struct Foundation.URL #if os(macOS) -import class Foundation.Bundle + import class Foundation.Bundle #endif import OrderedCollections -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph import PackageLoading import PackageModel @@ -140,7 +139,7 @@ public func testWithTemporaryDirectory( fixtureDir: fixtureDir, in: tmpDirPath, copyName: copyName, - createGitRepo:createGitRepo + createGitRepo: createGitRepo ) return try body(preparedFixture) } @@ -185,7 +184,7 @@ public func testWithTemporaryDirectory( fixtureDir: fixtureDir, in: tmpDirPath, copyName: copyName, - createGitRepo:createGitRepo + createGitRepo: createGitRepo ) return try body(preparedFixture) } @@ -228,7 +227,7 @@ public enum TestError: Error { fixtureDir: fixtureDir, in: tmpDirPath, copyName: copyName, - createGitRepo:createGitRepo + createGitRepo: createGitRepo ) return try await body(preparedFixture) } @@ -273,7 +272,7 @@ public enum TestError: Error { fixtureDir: fixtureDir, in: tmpDirPath, copyName: copyName, - createGitRepo:createGitRepo + createGitRepo: createGitRepo ) return try await body(preparedFixture) } @@ -318,11 +317,11 @@ fileprivate func setup( ) throws -> AbsolutePath { func copy(from srcDir: AbsolutePath, to dstDir: AbsolutePath) throws { #if os(Windows) - try localFileSystem.copy(from: srcDir, to: dstDir) + try localFileSystem.copy(from: srcDir, to: dstDir) #else - try Process.checkNonZeroExit(args: "cp", "-R", "-H", srcDir.pathString, dstDir.pathString) + try Process.checkNonZeroExit(args: "cp", "-R", "-H", srcDir.pathString, dstDir.pathString) #endif - + // Ensure we get a clean test fixture. try localFileSystem.removeFileTree(dstDir.appending(component: ".build")) try localFileSystem.removeFileTree(dstDir.appending(component: ".swiftpm")) @@ -405,7 +404,7 @@ public func getBuildSystemArgs(for buildSystem: BuildSystemProvider.Kind?) -> [S return [ "--build-system", - "\(system)" + "\(system)", ] } @@ -549,7 +548,8 @@ private func swiftArgs( return args } -@available(*, +@available( + *, deprecated, renamed: "loadModulesGraph", message: "Rename for consistency: the type of this functions return value is named `ModulesGraph`." @@ -694,18 +694,18 @@ public func getNumberOfMatches(of match: String, in value: String) -> Int { } public extension String { - var withSwiftLineEnding: String { + var withSwiftLineEnding: String { return replacingOccurrences(of: "\r\n", with: "\n") } } public func executableName(_ name: String) -> String { -#if os(Windows) - if name.count > 4, name.suffix(from: name.index(name.endIndex, offsetBy: -4)) == ProcessInfo.exeSuffix { - return name - } - return "\(name)\(ProcessInfo.exeSuffix)" -#else - return name -#endif -} \ No newline at end of file + #if os(Windows) + if name.count > 4, name.suffix(from: name.index(name.endIndex, offsetBy: -4)) == ProcessInfo.exeSuffix { + return name + } + return "\(name)\(ProcessInfo.exeSuffix)" + #else + return name + #endif +} diff --git a/Sources/swift-bootstrap/main.swift b/Sources/swift-bootstrap/main.swift index e93f246372a..30e798fd360 100644 --- a/Sources/swift-bootstrap/main.swift +++ b/Sources/swift-bootstrap/main.swift @@ -16,8 +16,7 @@ import _Concurrency import Build import Dispatch -@_spi(SwiftPMInternal) -import DriverSupport +@_spi(SwiftPMInternal) import DriverSupport import Foundation import OrderedCollections @@ -47,9 +46,11 @@ struct SwiftBootstrapBuildTool: AsyncParsableCommand { shouldDisplay: false ) - @Option(name: .customLong("package-path"), - help: "Specify the package path to operate on (default current directory). This changes the working directory before any other operation.", - completion: .directory) + @Option( + name: .customLong("package-path"), + help: "Specify the package path to operate on (default current directory). This changes the working directory before any other operation.", + completion: .directory + ) public var packageDirectory: AbsolutePath? /// The custom .build directory, if provided. @@ -66,42 +67,58 @@ struct SwiftBootstrapBuildTool: AsyncParsableCommand { @Option(name: .shortAndLong, help: "Build with configuration.") public var configuration: BuildConfiguration = .debug - @Option(name: .customLong("Xcc", withSingleDash: true), - parsing: .unconditionalSingleValue, - help: "Pass flag through to all C compiler invocations.") + @Option( + name: .customLong("Xcc", withSingleDash: true), + parsing: .unconditionalSingleValue, + help: "Pass flag through to all C compiler invocations." + ) var cCompilerFlags: [String] = [] - @Option(name: .customLong("Xswiftc", withSingleDash: true), - parsing: .unconditionalSingleValue, - help: "Pass flag through to all Swift compiler invocations.") + @Option( + name: .customLong("Xswiftc", withSingleDash: true), + parsing: .unconditionalSingleValue, + help: "Pass flag through to all Swift compiler invocations." + ) var swiftCompilerFlags: [String] = [] - @Option(name: .customLong("Xlinker", withSingleDash: true), - parsing: .unconditionalSingleValue, - help: "Pass flag through to all linker invocations.") + @Option( + name: .customLong("Xlinker", withSingleDash: true), + parsing: .unconditionalSingleValue, + help: "Pass flag through to all linker invocations." + ) var linkerFlags: [String] = [] - @Option(name: .customLong("Xcxx", withSingleDash: true), - parsing: .unconditionalSingleValue, - help: "Pass flag through to all C++ compiler invocations.") + @Option( + name: .customLong("Xcxx", withSingleDash: true), + parsing: .unconditionalSingleValue, + help: "Pass flag through to all C++ compiler invocations." + ) var cxxCompilerFlags: [String] = [] - @Option(name: .customLong("Xxcbuild", withSingleDash: true), - parsing: .unconditionalSingleValue, - help: ArgumentHelp( - "Pass flag through to the Xcode build system invocations.", - visibility: .hidden)) + @Option( + name: .customLong("Xxcbuild", withSingleDash: true), + parsing: .unconditionalSingleValue, + help: ArgumentHelp( + "Pass flag through to the Xcode build system invocations.", + visibility: .hidden + ) + ) public var xcbuildFlags: [String] = [] - @Option(name: .customLong("Xbuild-tools-swiftc", withSingleDash: true), - parsing: .unconditionalSingleValue, - help: ArgumentHelp("Pass flag to the manifest build invocation.", - visibility: .hidden)) + @Option( + name: .customLong("Xbuild-tools-swiftc", withSingleDash: true), + parsing: .unconditionalSingleValue, + help: ArgumentHelp( + "Pass flag to the manifest build invocation.", + visibility: .hidden + ) + ) public var manifestFlags: [String] = [] @Option( - name: .customLong("arch"), - help: ArgumentHelp("Build the package for the these architectures.", visibility: .hidden)) + name: .customLong("arch"), + help: ArgumentHelp("Build the package for the these architectures.", visibility: .hidden) + ) public var architectures: [String] = [] /// The verbosity of informational output. @@ -137,12 +154,12 @@ struct SwiftBootstrapBuildTool: AsyncParsableCommand { private var buildSystem: BuildSystemProvider.Kind { #if os(macOS) - // Force the Xcode build system if we want to build more than one arch. - return self.architectures.count > 1 ? .xcode : self._buildSystem + // Force the Xcode build system if we want to build more than one arch. + return self.architectures.count > 1 ? .xcode : self._buildSystem #else - // Use whatever the build system provided by the command-line, or default fallback - // on other platforms. - return self._buildSystem + // Use whatever the build system provided by the command-line, or default fallback + // on other platforms. + return self._buildSystem #endif } @@ -188,9 +205,7 @@ struct SwiftBootstrapBuildTool: AsyncParsableCommand { } let scratchDirectory = - try BuildSystemUtilities.getEnvBuildPath(workingDir: cwd) ?? - self.scratchDirectory ?? - packagePath.appending(".build") + try BuildSystemUtilities.getEnvBuildPath(workingDir: cwd) ?? self.scratchDirectory ?? packagePath.appending(".build") let builder = try Builder( fileSystem: localFileSystem, @@ -235,14 +250,14 @@ struct SwiftBootstrapBuildTool: AsyncParsableCommand { ), environment: environment ) - self.targetToolchain = hostToolchain // TODO: support cross-compilation? + self.targetToolchain = hostToolchain // TODO: support cross-compilation? self.fileSystem = fileSystem self.observabilityScope = observabilityScope self.logLevel = logLevel } func build( - packagePath: AbsolutePath, + packagePath: AbsolutePath, scratchDirectory: AbsolutePath, buildSystem: BuildSystemProvider.Kind, configuration: BuildConfiguration, @@ -403,7 +418,7 @@ struct SwiftBootstrapBuildTool: AsyncParsableCommand { func loadPackageGraph(packagePath: AbsolutePath, manifestLoader: ManifestLoader) async throws -> ModulesGraph { let rootPackageRef = PackageReference(identity: .init(path: packagePath), kind: .root(packagePath)) - let rootPackageManifest = try await self.loadManifest(manifestLoader: manifestLoader, package: rootPackageRef) + let rootPackageManifest = try await self.loadManifest(manifestLoader: manifestLoader, package: rootPackageRef) var loadedManifests = [PackageIdentity: Manifest]() loadedManifests[rootPackageRef.identity] = rootPackageManifest @@ -413,7 +428,7 @@ struct SwiftBootstrapBuildTool: AsyncParsableCommand { _ = try await topologicalSort(input) { pair in // When bootstrapping no special trait build configuration is used let dependenciesRequired = try pair.item.dependenciesRequired(for: .everything) - let dependenciesToLoad = dependenciesRequired.map{ $0.packageRef }.filter { !loadedManifests.keys.contains($0.identity) } + let dependenciesToLoad = dependenciesRequired.map { $0.packageRef }.filter { !loadedManifests.keys.contains($0.identity) } let dependenciesManifests = try await self.loadManifests(manifestLoader: manifestLoader, packages: dependenciesToLoad) dependenciesManifests.forEach { loadedManifests[$0.key] = $0.value } return dependenciesRequired.compactMap { dependency in @@ -440,7 +455,7 @@ struct SwiftBootstrapBuildTool: AsyncParsableCommand { prebuilts: [:], fileSystem: fileSystem, observabilityScope: observabilityScope, - enabledTraitsMap: [:] // When bootstrapping no special trait build configuration is used + enabledTraitsMap: [:] // When bootstrapping no special trait build configuration is used ) } @@ -448,7 +463,7 @@ struct SwiftBootstrapBuildTool: AsyncParsableCommand { manifestLoader: ManifestLoader, packages: [PackageReference] ) async throws -> [PackageIdentity: Manifest] { - return try await withThrowingTaskGroup(of: (package:PackageReference, manifest:Manifest).self) { group in + return try await withThrowingTaskGroup(of: (package: PackageReference, manifest: Manifest).self) { group in for package in packages { group.addTask { try await (package, self.loadManifest(manifestLoader: manifestLoader, package: package)) @@ -518,12 +533,17 @@ extension BuildConfiguration: ExpressibleByArgument {} extension BuildSystemProvider.Kind: ExpressibleByArgument {} public func topologicalSort( - _ nodes: [T], successors: (T) async throws -> [T] + _ nodes: [T], + successors: (T) async throws -> [T] ) async throws -> [T] { // Implements a topological sort via recursion and reverse postorder DFS. - func visit(_ node: T, - _ stack: inout OrderedSet, _ visited: inout Set, _ result: inout [T], - _ successors: (T) async throws -> [T]) async throws { + func visit( + _ node: T, + _ stack: inout OrderedSet, + _ visited: inout Set, + _ result: inout [T], + _ successors: (T) async throws -> [T] + ) async throws { // Mark this node as visited -- we are done if it already was. if !visited.insert(node).inserted { return diff --git a/Sources/swift-build-prebuilts/BuildPrebuilts.swift b/Sources/swift-build-prebuilts/BuildPrebuilts.swift index 88bf4516cd3..38ae2c4e344 100644 --- a/Sources/swift-build-prebuilts/BuildPrebuilts.swift +++ b/Sources/swift-build-prebuilts/BuildPrebuilts.swift @@ -31,7 +31,7 @@ struct Artifact: Codable { var libraryName: String? var products: [String]? var includePath: [String]? - var cModules: [String]? // deprecated, includePath is the way forward + var cModules: [String]? // deprecated, includePath is the way forward var swiftVersion: String? } @@ -162,12 +162,12 @@ struct BuildPrebuilts: AsyncParsableCommand { var packageContents = try String(contentsOf: packageFile.asURL) packageContents += """ - package.products += [ - .library(name: "\(libraryName)", type: .static, targets: [ - \(libraryTargets.map({ "\"\($0.name)\"" }).joined(separator: ",")) - ]) - ] - """ + package.products += [ + .library(name: "\(libraryName)", type: .static, targets: [ + \(libraryTargets.map({ "\"\($0.name)\"" }).joined(separator: ",")) + ]) + ] + """ try packageContents.write(to: packageFile.asURL, atomically: true, encoding: .utf8) // Build @@ -201,19 +201,19 @@ struct BuildPrebuilts: AsyncParsableCommand { // Zip it up let contentDirs = ["lib", "Modules"] -#if os(Windows) - let zipFile = versionDir.appending("\(swiftVersion)-\(libraryName)-\(platform).zip") - try await shell("tar -acf \(zipFile.pathString) \(contentDirs.joined(separator: " "))", cwd: stageDir) - let contents = try ByteString(Data(contentsOf: zipFile.asURL)) -#elseif os(Linux) - let tarFile = versionDir.appending("\(swiftVersion)-\(libraryName)-\(platform).tar.gz") - try await shell("tar -zcf \(tarFile.pathString) \(contentDirs.joined(separator: " "))", cwd: stageDir) - let contents = try ByteString(Data(contentsOf: tarFile.asURL)) -#else - let zipFile = versionDir.appending("\(swiftVersion)-\(libraryName)-\(platform).zip") - try await shell("zip -r \(zipFile.pathString) \(contentDirs.joined(separator: " "))", cwd: stageDir) - let contents = try ByteString(Data(contentsOf: zipFile.asURL)) -#endif + #if os(Windows) + let zipFile = versionDir.appending("\(swiftVersion)-\(libraryName)-\(platform).zip") + try await shell("tar -acf \(zipFile.pathString) \(contentDirs.joined(separator: " "))", cwd: stageDir) + let contents = try ByteString(Data(contentsOf: zipFile.asURL)) + #elseif os(Linux) + let tarFile = versionDir.appending("\(swiftVersion)-\(libraryName)-\(platform).tar.gz") + try await shell("tar -zcf \(tarFile.pathString) \(contentDirs.joined(separator: " "))", cwd: stageDir) + let contents = try ByteString(Data(contentsOf: tarFile.asURL)) + #else + let zipFile = versionDir.appending("\(swiftVersion)-\(libraryName)-\(platform).zip") + try await shell("zip -r \(zipFile.pathString) \(contentDirs.joined(separator: " "))", cwd: stageDir) + let contents = try ByteString(Data(contentsOf: zipFile.asURL)) + #endif // Manifest fragment for the zip file let checksum = SHA256().hash(contents).hexadecimalRepresentation @@ -222,7 +222,7 @@ struct BuildPrebuilts: AsyncParsableCommand { checksum: checksum, libraryName: libraryName, products: package.products.map(\.name), - includePath: cModules.map({ $0.includeDir.relative(to: repoDir ).pathString.replacingOccurrences(of: "\\", with: "/") }), + includePath: cModules.map({ $0.includeDir.relative(to: repoDir).pathString.replacingOccurrences(of: "\\", with: "/") }), swiftVersion: swiftVersion ) @@ -268,9 +268,9 @@ struct BuildPrebuilts: AsyncParsableCommand { if artifact.swiftVersion == nil || artifact.libraryName == nil { let regex = try Regex(#"(.+)-([^-]+)-[^-]+.zip.json"#) if let match = try regex.firstMatch(in: $0), - match.count > 2, - let swiftVersion = match[1].substring, - let libraryName = match[2].substring + match.count > 2, + let swiftVersion = match[1].substring, + let libraryName = match[2].substring { artifact.swiftVersion = .init(swiftVersion) artifact.libraryName = .init(libraryName) @@ -380,7 +380,7 @@ struct BuildPrebuilts: AsyncParsableCommand { certChainPathStrs = [ certsPath.appending("Test_rsa.cer").pathString, certsPath.appending("TestIntermediateCA.cer").pathString, - certsPath.appending("TestRootCA.cer").pathString + certsPath.appending("TestRootCA.cer").pathString, ] } @@ -421,15 +421,15 @@ struct BuildPrebuilts: AsyncParsableCommand { } func canBuild(_ platform: Workspace.PrebuiltsManifest.Platform) -> Bool { -#if os(macOS) - return platform.os == .macos -#elseif os(Windows) - return platform.os == .windows -#elseif os(Linux) - return platform == Workspace.PrebuiltsManifest.Platform.hostPlatform -#else - return false -#endif + #if os(macOS) + return platform.os == .macos + #elseif os(Windows) + return platform.os == .windows + #elseif os(Linux) + return platform == Workspace.PrebuiltsManifest.Platform.hostPlatform + #else + return false + #endif } func make(path: String) throws -> AbsolutePath { @@ -447,11 +447,11 @@ struct BuildPrebuilts: AsyncParsableCommand { func shell(_ command: String, cwd: AbsolutePath) async throws { _ = FileManager.default.changeCurrentDirectoryPath(cwd.pathString) -#if os(Windows) - let arguments = ["C:\\Windows\\System32\\cmd.exe", "/c", command] -#else - let arguments = ["/bin/bash", "-c", command] -#endif + #if os(Windows) + let arguments = ["C:\\Windows\\System32\\cmd.exe", "/c", command] + #else + let arguments = ["/bin/bash", "-c", command] + #endif let process = AsyncProcess( arguments: arguments, outputRedirection: .none @@ -464,13 +464,13 @@ func shell(_ command: String, cwd: AbsolutePath) async throws { if code != 0 { throw StringError("Command exited with code \(code): \(command)") } -#if os(Windows) - case .abnormal(exception: let exception): - throw StringError("Command threw exception \(exception): \(command)") -#else - case .signalled(signal: let signal): - throw StringError("Command exited on signal \(signal): \(command)") -#endif + #if os(Windows) + case .abnormal(exception: let exception): + throw StringError("Command threw exception \(exception): \(command)") + #else + case .signalled(signal: let signal): + throw StringError("Command exited on signal \(signal): \(command)") + #endif } } diff --git a/Sources/swift-package-manager/SwiftPM.swift b/Sources/swift-package-manager/SwiftPM.swift index 3268423b983..89dbd7a6285 100644 --- a/Sources/swift-package-manager/SwiftPM.swift +++ b/Sources/swift-package-manager/SwiftPM.swift @@ -19,8 +19,7 @@ import PackageCollectionsCommand import PackageRegistryCommand let firstArg = CommandLine.arguments[0] -let baseNameWithoutExtension = (try? AbsolutePath(validating: firstArg).basenameWithoutExt) ?? - (try? RelativePath(validating: firstArg).basenameWithoutExt) +let baseNameWithoutExtension = (try? AbsolutePath(validating: firstArg).basenameWithoutExt) ?? (try? RelativePath(validating: firstArg).basenameWithoutExt) @main struct SwiftPM { diff --git a/Sources/swiftpm-testing-helper/Entrypoint.swift b/Sources/swiftpm-testing-helper/Entrypoint.swift index 93d27cb70de..567575e6e80 100644 --- a/Sources/swiftpm-testing-helper/Entrypoint.swift +++ b/Sources/swiftpm-testing-helper/Entrypoint.swift @@ -11,9 +11,9 @@ //===----------------------------------------------------------------------===// #if canImport(Darwin) -import Darwin.C + import Darwin.C #elseif canImport(Android) -import Android + import Android #endif @main @@ -23,14 +23,15 @@ struct Entrypoint { if args.count >= 3, args[1] == "--test-bundle-path" { let bundlePath = args[2] #if canImport(Darwin) - let flags = RTLD_LAZY | RTLD_FIRST + let flags = RTLD_LAZY | RTLD_FIRST #else - let flags = RTLD_LAZY + let flags = RTLD_LAZY #endif guard let image = dlopen(bundlePath, flags) else { - let errorMessage: String = dlerror().flatMap { - String(validatingCString: $0) - } ?? "An unknown error occurred." + let errorMessage: String = + dlerror().flatMap { + String(validatingCString: $0) + } ?? "An unknown error occurred." fatalError("Failed to open test bundle at path \(bundlePath): \(errorMessage)") } defer { diff --git a/Tests/BasicsTests/Archiver/TarArchiverTests.swift b/Tests/BasicsTests/Archiver/TarArchiverTests.swift index ba80f19d43a..0c65fee4eb0 100644 --- a/Tests/BasicsTests/Archiver/TarArchiverTests.swift +++ b/Tests/BasicsTests/Archiver/TarArchiverTests.swift @@ -12,7 +12,7 @@ import Basics @testable import struct Basics.TarArchiver -import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported +import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported import _InternalTestSupport import XCTest @@ -70,9 +70,9 @@ final class TarArchiverTests: XCTestCase { .appending(components: "Inputs", "invalid_archive.tar.gz") await XCTAssertAsyncThrowsError(try await archiver.extract(from: inputArchivePath, to: tmpdir)) { error in #if os(Linux) - XCTAssertMatch((error as? StringError)?.description, .contains("not in gzip format")) + XCTAssertMatch((error as? StringError)?.description, .contains("not in gzip format")) #else - XCTAssertMatch((error as? StringError)?.description, .contains("Unrecognized archive format")) + XCTAssertMatch((error as? StringError)?.description, .contains("Unrecognized archive format")) #endif } } @@ -94,7 +94,7 @@ final class TarArchiverTests: XCTestCase { try await XCTAssertAsyncFalse(try await archiver.validate(path: path)) } // error - try await testWithTemporaryDirectory { _ in + try await testWithTemporaryDirectory { _ in let archiver = TarArchiver(fileSystem: localFileSystem) let path = AbsolutePath.root.appending("does_not_exist.tar.gz") await XCTAssertAsyncThrowsError(try await archiver.validate(path: path)) { error in @@ -105,9 +105,9 @@ final class TarArchiverTests: XCTestCase { func testCompress() async throws { #if !os(Windows) - guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { - throw XCTSkip("working directory not supported on this platform") - } + guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { + throw XCTSkip("working directory not supported on this platform") + } #endif try await testWithTemporaryDirectory { tmpdir in diff --git a/Tests/BasicsTests/Archiver/UniversalArchiverTests.swift b/Tests/BasicsTests/Archiver/UniversalArchiverTests.swift index 11b6bdab7dc..a9996402d2d 100644 --- a/Tests/BasicsTests/Archiver/UniversalArchiverTests.swift +++ b/Tests/BasicsTests/Archiver/UniversalArchiverTests.swift @@ -13,7 +13,7 @@ import Basics @testable import struct Basics.TarArchiver @testable import struct Basics.ZipArchiver -import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported +import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported import _InternalTestSupport import XCTest @@ -91,20 +91,20 @@ final class UniversalArchiverTests: XCTestCase { .appending(components: "Inputs", "invalid_archive.tar.gz") await XCTAssertAsyncThrowsError(try await archiver.extract(from: inputArchivePath, to: tmpdir)) { error in #if os(Linux) - XCTAssertMatch((error as? StringError)?.description, .contains("not in gzip format")) + XCTAssertMatch((error as? StringError)?.description, .contains("not in gzip format")) #else - XCTAssertMatch((error as? StringError)?.description, .contains("Unrecognized archive format")) + XCTAssertMatch((error as? StringError)?.description, .contains("Unrecognized archive format")) #endif } inputArchivePath = AbsolutePath(#file).parentDirectory .appending(components: "Inputs", "invalid_archive.zip") await XCTAssertAsyncThrowsError(try await archiver.extract(from: inputArchivePath, to: tmpdir)) { error in -#if os(Windows) || os(FreeBSD) - XCTAssertMatch((error as? StringError)?.description, .contains("Unrecognized archive format")) -#else - XCTAssertMatch((error as? StringError)?.description, .contains("End-of-central-directory signature not found")) -#endif + #if os(Windows) || os(FreeBSD) + XCTAssertMatch((error as? StringError)?.description, .contains("Unrecognized archive format")) + #else + XCTAssertMatch((error as? StringError)?.description, .contains("End-of-central-directory signature not found")) + #endif } } } @@ -136,9 +136,9 @@ final class UniversalArchiverTests: XCTestCase { func testCompress() async throws { #if !os(Windows) - guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { - throw XCTSkip("working directory not supported on this platform") - } + guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { + throw XCTSkip("working directory not supported on this platform") + } #endif try await testWithTemporaryDirectory { tmpdir in diff --git a/Tests/BasicsTests/Archiver/ZipArchiverTests.swift b/Tests/BasicsTests/Archiver/ZipArchiverTests.swift index 83d4df368b5..9b5e244887e 100644 --- a/Tests/BasicsTests/Archiver/ZipArchiverTests.swift +++ b/Tests/BasicsTests/Archiver/ZipArchiverTests.swift @@ -14,7 +14,7 @@ import Basics @testable import struct Basics.ZipArchiver import _InternalTestSupport import XCTest -import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported +import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported import struct TSCBasic.FileSystemError @@ -76,12 +76,12 @@ final class ZipArchiverTests: XCTestCase { let inputArchivePath = AbsolutePath(#file).parentDirectory .appending(components: "Inputs", "invalid_archive.zip") await XCTAssertAsyncThrowsError(try await archiver.extract(from: inputArchivePath, to: tmpdir)) { error in -#if os(Windows) || os(FreeBSD) - // On FreeBSD, unzip (bsdunzip) is backed by libarchive - XCTAssertMatch((error as? StringError)?.description, .contains("Unrecognized archive format")) -#else - XCTAssertMatch((error as? StringError)?.description, .contains("End-of-central-directory signature not found")) -#endif + #if os(Windows) || os(FreeBSD) + // On FreeBSD, unzip (bsdunzip) is backed by libarchive + XCTAssertMatch((error as? StringError)?.description, .contains("Unrecognized archive format")) + #else + XCTAssertMatch((error as? StringError)?.description, .contains("End-of-central-directory signature not found")) + #endif } } } @@ -113,69 +113,69 @@ final class ZipArchiverTests: XCTestCase { func testCompress() async throws { #if !os(Windows) - guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { - throw XCTSkip("working directory not supported on this platform") - } + guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { + throw XCTSkip("working directory not supported on this platform") + } #endif - try await testWithTemporaryDirectory { tmpdir in - let archiver = ZipArchiver(fileSystem: localFileSystem) - - let rootDir = tmpdir.appending(component: UUID().uuidString) - try localFileSystem.createDirectory(rootDir) - try localFileSystem.writeFileContents(rootDir.appending("file1.txt"), string: "Hello World!") - - let dir1 = rootDir.appending("dir1") - try localFileSystem.createDirectory(dir1) - try localFileSystem.writeFileContents(dir1.appending("file2.txt"), string: "Hello World 2!") - - let dir2 = dir1.appending("dir2") - try localFileSystem.createDirectory(dir2) - try localFileSystem.writeFileContents(dir2.appending("file3.txt"), string: "Hello World 3!") - try localFileSystem.writeFileContents(dir2.appending("file4.txt"), string: "Hello World 4!") - try localFileSystem.createSymbolicLink(dir2.appending("file5.txt"), pointingAt: dir1.appending("file2.txt"), relative: true) - - let archivePath = tmpdir.appending(component: UUID().uuidString + ".zip") - try await archiver.compress(directory: rootDir, to: archivePath) - XCTAssertFileExists(archivePath) - - let extractRootDir = tmpdir.appending(component: UUID().uuidString) - try localFileSystem.createDirectory(extractRootDir) - try await archiver.extract(from: archivePath, to: extractRootDir) - try localFileSystem.stripFirstLevel(of: extractRootDir) - - XCTAssertFileExists(extractRootDir.appending("file1.txt")) - XCTAssertEqual( - try? localFileSystem.readFileContents(extractRootDir.appending("file1.txt")), - "Hello World!" - ) - - let extractedDir1 = extractRootDir.appending("dir1") - XCTAssertDirectoryExists(extractedDir1) - XCTAssertFileExists(extractedDir1.appending("file2.txt")) - XCTAssertEqual( - try? localFileSystem.readFileContents(extractedDir1.appending("file2.txt")), - "Hello World 2!" - ) - - let extractedDir2 = extractedDir1.appending("dir2") - XCTAssertDirectoryExists(extractedDir2) - XCTAssertFileExists(extractedDir2.appending("file3.txt")) - XCTAssertEqual( - try? localFileSystem.readFileContents(extractedDir2.appending("file3.txt")), - "Hello World 3!" - ) - XCTAssertFileExists(extractedDir2.appending("file4.txt")) - XCTAssertEqual( - try? localFileSystem.readFileContents(extractedDir2.appending("file4.txt")), - "Hello World 4!" - ) - - XCTAssertTrue(localFileSystem.isSymlink(extractedDir2.appending("file5.txt"))) - XCTAssertEqual( - try? localFileSystem.readFileContents(extractedDir2.appending("file5.txt")), - try? localFileSystem.readFileContents(extractedDir1.appending("file2.txt")) - ) - } - } + try await testWithTemporaryDirectory { tmpdir in + let archiver = ZipArchiver(fileSystem: localFileSystem) + + let rootDir = tmpdir.appending(component: UUID().uuidString) + try localFileSystem.createDirectory(rootDir) + try localFileSystem.writeFileContents(rootDir.appending("file1.txt"), string: "Hello World!") + + let dir1 = rootDir.appending("dir1") + try localFileSystem.createDirectory(dir1) + try localFileSystem.writeFileContents(dir1.appending("file2.txt"), string: "Hello World 2!") + + let dir2 = dir1.appending("dir2") + try localFileSystem.createDirectory(dir2) + try localFileSystem.writeFileContents(dir2.appending("file3.txt"), string: "Hello World 3!") + try localFileSystem.writeFileContents(dir2.appending("file4.txt"), string: "Hello World 4!") + try localFileSystem.createSymbolicLink(dir2.appending("file5.txt"), pointingAt: dir1.appending("file2.txt"), relative: true) + + let archivePath = tmpdir.appending(component: UUID().uuidString + ".zip") + try await archiver.compress(directory: rootDir, to: archivePath) + XCTAssertFileExists(archivePath) + + let extractRootDir = tmpdir.appending(component: UUID().uuidString) + try localFileSystem.createDirectory(extractRootDir) + try await archiver.extract(from: archivePath, to: extractRootDir) + try localFileSystem.stripFirstLevel(of: extractRootDir) + + XCTAssertFileExists(extractRootDir.appending("file1.txt")) + XCTAssertEqual( + try? localFileSystem.readFileContents(extractRootDir.appending("file1.txt")), + "Hello World!" + ) + + let extractedDir1 = extractRootDir.appending("dir1") + XCTAssertDirectoryExists(extractedDir1) + XCTAssertFileExists(extractedDir1.appending("file2.txt")) + XCTAssertEqual( + try? localFileSystem.readFileContents(extractedDir1.appending("file2.txt")), + "Hello World 2!" + ) + + let extractedDir2 = extractedDir1.appending("dir2") + XCTAssertDirectoryExists(extractedDir2) + XCTAssertFileExists(extractedDir2.appending("file3.txt")) + XCTAssertEqual( + try? localFileSystem.readFileContents(extractedDir2.appending("file3.txt")), + "Hello World 3!" + ) + XCTAssertFileExists(extractedDir2.appending("file4.txt")) + XCTAssertEqual( + try? localFileSystem.readFileContents(extractedDir2.appending("file4.txt")), + "Hello World 4!" + ) + + XCTAssertTrue(localFileSystem.isSymlink(extractedDir2.appending("file5.txt"))) + XCTAssertEqual( + try? localFileSystem.readFileContents(extractedDir2.appending("file5.txt")), + try? localFileSystem.readFileContents(extractedDir1.appending("file2.txt")) + ) + } + } } diff --git a/Tests/BasicsTests/AsyncProcessTests.swift b/Tests/BasicsTests/AsyncProcessTests.swift index 656831ef3c2..46edfd1bd0b 100644 --- a/Tests/BasicsTests/AsyncProcessTests.swift +++ b/Tests/BasicsTests/AsyncProcessTests.swift @@ -13,7 +13,7 @@ import _Concurrency import Basics import XCTest -import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported +import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported import class TSCBasic.BufferedOutputByteStream import struct TSCBasic.ByteString @@ -22,9 +22,9 @@ import class TSCBasic.Thread import func TSCBasic.withTemporaryFile #if os(Windows) -let catExecutable = "type" + let catExecutable = "type" #else -let catExecutable = "cat" + let catExecutable = "cat" #endif final class AsyncProcessTests: XCTestCase { @@ -32,19 +32,19 @@ final class AsyncProcessTests: XCTestCase { let catExecutableArgs = getAsyncProcessArgs(executable: catExecutable) func testBasicsProcess() throws { - let process = AsyncProcess(arguments: echoExecutableArgs + ["hello"]) - try process.launch() - let result = try process.waitUntilExit() - XCTAssertEqual(try result.utf8Output(), "hello\(ProcessInfo.EOL)") - XCTAssertEqual(result.exitStatus, .terminated(code: 0)) - XCTAssertEqual(result.arguments, process.arguments) + let process = AsyncProcess(arguments: echoExecutableArgs + ["hello"]) + try process.launch() + let result = try process.waitUntilExit() + XCTAssertEqual(try result.utf8Output(), "hello\(ProcessInfo.EOL)") + XCTAssertEqual(result.exitStatus, .terminated(code: 0)) + XCTAssertEqual(result.arguments, process.arguments) } func testBasicsScript() throws { - let process = AsyncProcess(scriptName: "exit4\(ProcessInfo.batSuffix)") - try process.launch() - let result = try process.waitUntilExit() - XCTAssertEqual(result.exitStatus, .terminated(code: 4)) + let process = AsyncProcess(scriptName: "exit4\(ProcessInfo.batSuffix)") + try process.launch() + let result = try process.waitUntilExit() + XCTAssertEqual(result.exitStatus, .terminated(code: 4)) } func testPopenBasic() throws { @@ -70,11 +70,11 @@ final class AsyncProcessTests: XCTestCase { func testPopenLegacyAsync() throws { #if os(Windows) - let args = ["where.exe", "where"] - let answer = "C:\\Windows\\System32\\where.exe" + let args = ["where.exe", "where"] + let answer = "C:\\Windows\\System32\\where.exe" #else - let args = ["whoami"] - let answer = NSUserName() + let args = ["whoami"] + let answer = NSUserName() #endif var popenResult: Result? let group = DispatchGroup() @@ -98,11 +98,11 @@ final class AsyncProcessTests: XCTestCase { @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) func testPopenAsync() async throws { #if os(Windows) - let args = ["where.exe", "where"] - let answer = "C:\\Windows\\System32\\where.exe" + let args = ["where.exe", "where"] + let answer = "C:\\Windows\\System32\\where.exe" #else - let args = ["whoami"] - let answer = NSUserName() + let args = ["whoami"] + let answer = NSUserName() #endif let processResult: AsyncProcessResult do { @@ -148,9 +148,9 @@ final class AsyncProcessTests: XCTestCase { try testWithTemporaryDirectory { tmpdir in // This process should always work. #if os(Windows) - XCTAssertTrue(AsyncProcess.findExecutable("cmd.exe") != nil) + XCTAssertTrue(AsyncProcess.findExecutable("cmd.exe") != nil) #else - XCTAssertTrue(AsyncProcess.findExecutable("ls") != nil) + XCTAssertTrue(AsyncProcess.findExecutable("ls") != nil) #endif XCTAssertEqual(AsyncProcess.findExecutable("nonExistantProgram"), nil) @@ -159,13 +159,15 @@ final class AsyncProcessTests: XCTestCase { // Create a local nonexecutable file to test. let tempExecutable = tmpdir.appending(component: "nonExecutableProgram") #if os(Windows) - let exitScriptContent = ByteString("EXIT /B") + let exitScriptContent = ByteString("EXIT /B") #else - let exitScriptContent = ByteString(""" - #!/bin/sh - exit + let exitScriptContent = ByteString( + """ + #!/bin/sh + exit - """) + """ + ) #endif try localFileSystem.writeFileContents(tempExecutable, bytes: exitScriptContent) @@ -179,11 +181,14 @@ final class AsyncProcessTests: XCTestCase { try testWithTemporaryDirectory { tmpdir in // Create a local nonexecutable file to test. let tempExecutable = tmpdir.appending(component: "nonExecutableProgram") - try localFileSystem.writeFileContents(tempExecutable, bytes: """ - #!/bin/sh - exit + try localFileSystem.writeFileContents( + tempExecutable, + bytes: """ + #!/bin/sh + exit - """) + """ + ) try Environment.makeCustom(["PATH": tmpdir.pathString]) { do { @@ -243,9 +248,15 @@ final class AsyncProcessTests: XCTestCase { func testStdin() throws { var stdout = [UInt8]() - let process = AsyncProcess(scriptName: "in-to-out\(ProcessInfo.batSuffix)", outputRedirection: .stream(stdout: { stdoutBytes in - stdout += stdoutBytes - }, stderr: { _ in })) + let process = AsyncProcess( + scriptName: "in-to-out\(ProcessInfo.batSuffix)", + outputRedirection: .stream( + stdout: { stdoutBytes in + stdout += stdoutBytes + }, + stderr: { _ in } + ) + ) let stdinStream = try process.launch() stdinStream.write("hello\(ProcessInfo.EOL)") @@ -319,11 +330,11 @@ final class AsyncProcessTests: XCTestCase { try process.launch() let result = try process.waitUntilExit() #if os(Windows) - let expectedStdout = "simple output\(ProcessInfo.EOL)" - let expectedStderr = "simple error\(ProcessInfo.EOL)" + let expectedStdout = "simple output\(ProcessInfo.EOL)" + let expectedStderr = "simple error\(ProcessInfo.EOL)" #else - let expectedStdout = "simple error\(ProcessInfo.EOL)simple output\(ProcessInfo.EOL)" - let expectedStderr = "" + let expectedStdout = "simple error\(ProcessInfo.EOL)simple output\(ProcessInfo.EOL)" + let expectedStderr = "" #endif XCTAssertEqual(try result.utf8Output(), expectedStdout) XCTAssertEqual(try result.utf8stderrOutput(), expectedStderr) @@ -340,11 +351,11 @@ final class AsyncProcessTests: XCTestCase { let count = 16 * 1024 #if os(Windows) - let expectedStdout = String(repeating: "1", count: count) - let expectedStderr = String(repeating: "2", count: count) + let expectedStdout = String(repeating: "1", count: count) + let expectedStderr = String(repeating: "2", count: count) #else - let expectedStdout = String(repeating: "12", count: count) - let expectedStderr = "" + let expectedStdout = String(repeating: "12", count: count) + let expectedStderr = "" #endif XCTAssertEqual(try result.utf8Output(), expectedStdout) XCTAssertEqual(try result.utf8stderrOutput(), expectedStderr) @@ -354,11 +365,17 @@ final class AsyncProcessTests: XCTestCase { func testStdoutStdErrStreaming() throws { var stdout = [UInt8]() var stderr = [UInt8]() - let process = AsyncProcess(scriptName: "long-stdout-stderr\(ProcessInfo.batSuffix)", outputRedirection: .stream(stdout: { stdoutBytes in - stdout += stdoutBytes - }, stderr: { stderrBytes in - stderr += stderrBytes - })) + let process = AsyncProcess( + scriptName: "long-stdout-stderr\(ProcessInfo.batSuffix)", + outputRedirection: .stream( + stdout: { stdoutBytes in + stdout += stdoutBytes + }, + stderr: { stderrBytes in + stderr += stderrBytes + } + ) + ) try process.launch() try process.waitUntilExit() @@ -370,21 +387,28 @@ final class AsyncProcessTests: XCTestCase { func testStdoutStdErrStreamingRedirected() throws { var stdout = [UInt8]() var stderr = [UInt8]() - let process = AsyncProcess(scriptName: "long-stdout-stderr\(ProcessInfo.batSuffix)", outputRedirection: .stream(stdout: { stdoutBytes in - stdout += stdoutBytes - }, stderr: { stderrBytes in - stderr += stderrBytes - }, redirectStderr: true)) + let process = AsyncProcess( + scriptName: "long-stdout-stderr\(ProcessInfo.batSuffix)", + outputRedirection: .stream( + stdout: { stdoutBytes in + stdout += stdoutBytes + }, + stderr: { stderrBytes in + stderr += stderrBytes + }, + redirectStderr: true + ) + ) try process.launch() try process.waitUntilExit() let count = 16 * 1024 #if os(Windows) - let expectedStdout = String(repeating: "1", count: count) - let expectedStderr = String(repeating: "2", count: count) + let expectedStdout = String(repeating: "1", count: count) + let expectedStderr = String(repeating: "2", count: count) #else - let expectedStdout = String(repeating: "12", count: count) - let expectedStderr = "" + let expectedStdout = String(repeating: "12", count: count) + let expectedStderr = "" #endif XCTAssertEqual(String(bytes: stdout, encoding: .utf8), expectedStdout) XCTAssertEqual(String(bytes: stderr, encoding: .utf8), expectedStderr) @@ -392,10 +416,10 @@ final class AsyncProcessTests: XCTestCase { func testWorkingDirectory() throws { #if !os(Windows) - guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { - // Skip this test since it's not supported in this OS. - return - } + guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { + // Skip this test since it's not supported in this OS. + return + } #endif try withTemporaryDirectory(removeTreeOnDeinit: true) { tempDirPath in @@ -486,7 +510,7 @@ final class AsyncProcessTests: XCTestCase { try XCTSkipOnWindows(because: "https://github.com/swiftlang/swift-package-manager/issues/8547: 'swift test' was hanging.") let result = try await AsyncProcess.popen( - scriptName: "echo\(ProcessInfo.batSuffix)", // maps to 'processInputs/echo' script + scriptName: "echo\(ProcessInfo.batSuffix)", // maps to 'processInputs/echo' script stdout: { stdin, stdout in var counter = 0 stdin.write("Hello \(counter)\(ProcessInfo.EOL)") @@ -606,9 +630,9 @@ extension AsyncProcess { fileprivate func getAsyncProcessArgs(executable: String) -> [String] { #if os(Windows) - let args = ["cmd.exe", "/c", executable] + let args = ["cmd.exe", "/c", executable] #else - let args = [executable] + let args = [executable] #endif return args } diff --git a/Tests/BasicsTests/AuthorizationProviderTests.swift b/Tests/BasicsTests/AuthorizationProviderTests.swift index e99ad835a14..e7248519e4f 100644 --- a/Tests/BasicsTests/AuthorizationProviderTests.swift +++ b/Tests/BasicsTests/AuthorizationProviderTests.swift @@ -65,142 +65,141 @@ final class AuthorizationProviderTests: XCTestCase { func testProtocolHostPort() throws { #if !canImport(Security) - try XCTSkipIf(true) + try XCTSkipIf(true) #else - do { - let url = URL("http://localhost") - let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) - XCTAssertNotNil(parsed) - XCTAssertEqual(parsed?.protocol, "http") - XCTAssertEqual(parsed?.host, "localhost") - XCTAssertNil(parsed?.port) - XCTAssertEqual(parsed?.protocolCFString, kSecAttrProtocolHTTP) - XCTAssertEqual(parsed?.description, "http://localhost") - } - - do { - let url = URL("http://localhost:8080") - let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) - XCTAssertNotNil(parsed) - XCTAssertEqual(parsed?.protocol, "http") - XCTAssertEqual(parsed?.host, "localhost") - XCTAssertEqual(parsed?.port, 8080) - XCTAssertEqual(parsed?.protocolCFString, kSecAttrProtocolHTTP) - XCTAssertEqual(parsed?.description, "http://localhost:8080") - } - - do { - let url = URL("https://localhost") - let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) - XCTAssertNotNil(parsed) - XCTAssertEqual(parsed?.protocol, "https") - XCTAssertEqual(parsed?.host, "localhost") - XCTAssertNil(parsed?.port) - XCTAssertEqual(parsed?.protocolCFString, kSecAttrProtocolHTTPS) - XCTAssertEqual(parsed?.description, "https://localhost") - } - - do { - let url = URL("https://localhost:8080") - let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) - XCTAssertNotNil(parsed) - XCTAssertEqual(parsed?.protocol, "https") - XCTAssertEqual(parsed?.host, "localhost") - XCTAssertEqual(parsed?.port, 8080) - XCTAssertEqual(parsed?.protocolCFString, kSecAttrProtocolHTTPS) - XCTAssertEqual(parsed?.description, "https://localhost:8080") - } - - do { - let url = URL("https://:8080") - let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) - XCTAssertNil(parsed) - } + do { + let url = URL("http://localhost") + let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) + XCTAssertNotNil(parsed) + XCTAssertEqual(parsed?.protocol, "http") + XCTAssertEqual(parsed?.host, "localhost") + XCTAssertNil(parsed?.port) + XCTAssertEqual(parsed?.protocolCFString, kSecAttrProtocolHTTP) + XCTAssertEqual(parsed?.description, "http://localhost") + } + + do { + let url = URL("http://localhost:8080") + let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) + XCTAssertNotNil(parsed) + XCTAssertEqual(parsed?.protocol, "http") + XCTAssertEqual(parsed?.host, "localhost") + XCTAssertEqual(parsed?.port, 8080) + XCTAssertEqual(parsed?.protocolCFString, kSecAttrProtocolHTTP) + XCTAssertEqual(parsed?.description, "http://localhost:8080") + } + + do { + let url = URL("https://localhost") + let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) + XCTAssertNotNil(parsed) + XCTAssertEqual(parsed?.protocol, "https") + XCTAssertEqual(parsed?.host, "localhost") + XCTAssertNil(parsed?.port) + XCTAssertEqual(parsed?.protocolCFString, kSecAttrProtocolHTTPS) + XCTAssertEqual(parsed?.description, "https://localhost") + } + + do { + let url = URL("https://localhost:8080") + let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) + XCTAssertNotNil(parsed) + XCTAssertEqual(parsed?.protocol, "https") + XCTAssertEqual(parsed?.host, "localhost") + XCTAssertEqual(parsed?.port, 8080) + XCTAssertEqual(parsed?.protocolCFString, kSecAttrProtocolHTTPS) + XCTAssertEqual(parsed?.description, "https://localhost:8080") + } + + do { + let url = URL("https://:8080") + let parsed = KeychainAuthorizationProvider.ProtocolHostPort(from: url) + XCTAssertNil(parsed) + } #endif } func testKeychain_protocol() throws { #if !canImport(Security) || !ENABLE_KEYCHAIN_TEST - try XCTSkipIf(true) + try XCTSkipIf(true) #else - let provider = KeychainAuthorizationProvider(observabilityScope: ObservabilitySystem.NOOP) - - let user = UUID().uuidString + let provider = KeychainAuthorizationProvider(observabilityScope: ObservabilitySystem.NOOP) - let httpURL = URL("http://\(UUID().uuidString)") - let httpPassword = UUID().uuidString + let user = UUID().uuidString - let httpsURL = URL("https://\(UUID().uuidString)") - let httpsPassword = UUID().uuidString + let httpURL = URL("http://\(UUID().uuidString)") + let httpPassword = UUID().uuidString - // Add - try await provider.addOrUpdate(for: httpURL, user: user, password: httpPassword) - try await provider.addOrUpdate(for: httpsURL, user: user, password: httpsPassword) + let httpsURL = URL("https://\(UUID().uuidString)") + let httpsPassword = UUID().uuidString - self.assertAuthentication(provider, for: httpURL, expected: (user, httpPassword)) - self.assertAuthentication(provider, for: httpsURL, expected: (user, httpsPassword)) + // Add + try await provider.addOrUpdate(for: httpURL, user: user, password: httpPassword) + try await provider.addOrUpdate(for: httpsURL, user: user, password: httpsPassword) - // Update - let newHTTPPassword = UUID().uuidString - try await provider.addOrUpdate(for: httpURL, user: user, password: newHTTPPassword) + self.assertAuthentication(provider, for: httpURL, expected: (user, httpPassword)) + self.assertAuthentication(provider, for: httpsURL, expected: (user, httpsPassword)) - let newHTTPSPassword = UUID().uuidString - try await provider.addOrUpdate(for: httpsURL, user: user, password: newHTTPSPassword) + // Update + let newHTTPPassword = UUID().uuidString + try await provider.addOrUpdate(for: httpURL, user: user, password: newHTTPPassword) + let newHTTPSPassword = UUID().uuidString + try await provider.addOrUpdate(for: httpsURL, user: user, password: newHTTPSPassword) - // Existing password is updated - self.assertAuthentication(provider, for: httpURL, expected: (user, newHTTPPassword)) - self.assertAuthentication(provider, for: httpsURL, expected: (user, newHTTPSPassword)) + // Existing password is updated + self.assertAuthentication(provider, for: httpURL, expected: (user, newHTTPPassword)) + self.assertAuthentication(provider, for: httpsURL, expected: (user, newHTTPSPassword)) - // Delete - try await provider.remove(for: httpURL) - XCTAssertNil(provider.authentication(for: httpURL)) - self.assertAuthentication(provider, for: httpsURL, expected: (user, newHTTPSPassword)) + // Delete + try await provider.remove(for: httpURL) + XCTAssertNil(provider.authentication(for: httpURL)) + self.assertAuthentication(provider, for: httpsURL, expected: (user, newHTTPSPassword)) - try await provider.remove(for: httpsURL) - XCTAssertNil(provider.authentication(for: httpsURL)) + try await provider.remove(for: httpsURL) + XCTAssertNil(provider.authentication(for: httpsURL)) #endif } func testKeychain_port() throws { #if !canImport(Security) || !ENABLE_KEYCHAIN_TEST - try XCTSkipIf(true) + try XCTSkipIf(true) #else - let provider = KeychainAuthorizationProvider(observabilityScope: ObservabilitySystem.NOOP) + let provider = KeychainAuthorizationProvider(observabilityScope: ObservabilitySystem.NOOP) - let user = UUID().uuidString + let user = UUID().uuidString - let noPortURL = URL("http://\(UUID().uuidString)") - let noPortPassword = UUID().uuidString + let noPortURL = URL("http://\(UUID().uuidString)") + let noPortPassword = UUID().uuidString - let portURL = URL("http://\(UUID().uuidString):8971") - let portPassword = UUID().uuidString + let portURL = URL("http://\(UUID().uuidString):8971") + let portPassword = UUID().uuidString - // Add - try await provider.addOrUpdate(for: noPortURL, user: user, password: noPortPassword) - try await provider.addOrUpdate(for: portURL, user: user, password: portPassword) + // Add + try await provider.addOrUpdate(for: noPortURL, user: user, password: noPortPassword) + try await provider.addOrUpdate(for: portURL, user: user, password: portPassword) - self.assertAuthentication(provider, for: noPortURL, expected: (user, noPortPassword)) - self.assertAuthentication(provider, for: portURL, expected: (user, portPassword)) + self.assertAuthentication(provider, for: noPortURL, expected: (user, noPortPassword)) + self.assertAuthentication(provider, for: portURL, expected: (user, portPassword)) - // Update - let newPortPassword = UUID().uuidString - try await provider.addOrUpdate(for: portURL, user: user, password: newPortPassword) + // Update + let newPortPassword = UUID().uuidString + try await provider.addOrUpdate(for: portURL, user: user, password: newPortPassword) - let newNoPortPassword = UUID().uuidString - try await provider.addOrUpdate(for: noPortURL, user: user, password: newNoPortPassword) + let newNoPortPassword = UUID().uuidString + try await provider.addOrUpdate(for: noPortURL, user: user, password: newNoPortPassword) - // Existing password is updated - self.assertAuthentication(provider, for: portURL, expected: (user, newPortPassword)) - self.assertAuthentication(provider, for: noPortURL, expected: (user, newNoPortPassword)) + // Existing password is updated + self.assertAuthentication(provider, for: portURL, expected: (user, newPortPassword)) + self.assertAuthentication(provider, for: noPortURL, expected: (user, newNoPortPassword)) - // Delete - try await provider.remove(for: noPortURL) - XCTAssertNil(provider.authentication(for: noPortURL)) - self.assertAuthentication(provider, for: portURL, expected: (user, newPortPassword)) + // Delete + try await provider.remove(for: noPortURL) + XCTAssertNil(provider.authentication(for: noPortURL)) + self.assertAuthentication(provider, for: portURL, expected: (user, newPortPassword)) - try await provider.remove(for: portURL) - XCTAssertNil(provider.authentication(for: portURL)) + try await provider.remove(for: portURL) + XCTAssertNil(provider.authentication(for: portURL)) #endif } diff --git a/Tests/BasicsTests/CancellatorTests.swift b/Tests/BasicsTests/CancellatorTests.swift index e67030b0561..b187d96ede8 100644 --- a/Tests/BasicsTests/CancellatorTests.swift +++ b/Tests/BasicsTests/CancellatorTests.swift @@ -45,285 +45,285 @@ final class CancellatorTests: XCTestCase { } func testTSCProcess() throws { -#if os(macOS) - try withTemporaryDirectory { temporaryDirectory in - let scriptPath = temporaryDirectory.appending("script") - try localFileSystem.writeFileContents( - scriptPath, - string: """ - set -e - - echo "process started" - sleep 10 - echo "exit normally" - """ - ) - - let observability = ObservabilitySystem.makeForTesting() - let cancellator = Cancellator(observabilityScope: observability.topScope) - - // outputRedirection used to signal that the process started - let startSemaphore = ProcessStartedSemaphore(term: "process started") - let process = AsyncProcess( - arguments: ["bash", scriptPath.pathString], - outputRedirection: .stream( - stdout: startSemaphore.handleOutput, - stderr: startSemaphore.handleOutput + #if os(macOS) + try withTemporaryDirectory { temporaryDirectory in + let scriptPath = temporaryDirectory.appending("script") + try localFileSystem.writeFileContents( + scriptPath, + string: """ + set -e + + echo "process started" + sleep 10 + echo "exit normally" + """ ) - ) - let registrationKey = cancellator.register(process) - XCTAssertNotNil(registrationKey) + let observability = ObservabilitySystem.makeForTesting() + let cancellator = Cancellator(observabilityScope: observability.topScope) + + // outputRedirection used to signal that the process started + let startSemaphore = ProcessStartedSemaphore(term: "process started") + let process = AsyncProcess( + arguments: ["bash", scriptPath.pathString], + outputRedirection: .stream( + stdout: startSemaphore.handleOutput, + stderr: startSemaphore.handleOutput + ) + ) - let finishSemaphore = DispatchSemaphore(value: 0) - DispatchQueue.sharedConcurrent.async { - defer { finishSemaphore.signal() } - do { - try process.launch() - let result = try process.waitUntilExit() - print("process finished") - XCTAssertEqual(result.exitStatus, .signalled(signal: SIGINT)) - } catch { - XCTFail("failed launching process: \(error)") + let registrationKey = cancellator.register(process) + XCTAssertNotNil(registrationKey) + + let finishSemaphore = DispatchSemaphore(value: 0) + DispatchQueue.sharedConcurrent.async { + defer { finishSemaphore.signal() } + do { + try process.launch() + let result = try process.waitUntilExit() + print("process finished") + XCTAssertEqual(result.exitStatus, .signalled(signal: SIGINT)) + } catch { + XCTFail("failed launching process: \(error)") + } } - } - XCTAssertEqual(.success, startSemaphore.wait(timeout: .now() + .seconds(5)), "timeout starting tasks") - print("process started") + XCTAssertEqual(.success, startSemaphore.wait(timeout: .now() + .seconds(5)), "timeout starting tasks") + print("process started") - let canncelled = cancellator._cancel(deadline: .now() + .seconds(1)) - XCTAssertEqual(canncelled, 1) + let canncelled = cancellator._cancel(deadline: .now() + .seconds(1)) + XCTAssertEqual(canncelled, 1) - XCTAssertEqual(.success, finishSemaphore.wait(timeout: .now() + .seconds(5)), "timeout finishing tasks") + XCTAssertEqual(.success, finishSemaphore.wait(timeout: .now() + .seconds(5)), "timeout finishing tasks") - XCTAssertNoDiagnostics(observability.diagnostics) - } -#else - try XCTSkipIf(true, "skipping on non-macOS, signal traps do not work well on docker") -#endif + XCTAssertNoDiagnostics(observability.diagnostics) + } + #else + try XCTSkipIf(true, "skipping on non-macOS, signal traps do not work well on docker") + #endif } func testTSCProcessForceKill() throws { -#if os(macOS) - try withTemporaryDirectory { temporaryDirectory in - let scriptPath = temporaryDirectory.appending("script") - try localFileSystem.writeFileContents( - scriptPath, - string: """ - set -e - - trap_handler() { - echo "SIGINT trap" - sleep 10 - echo "exit SIGINT trap" - } - - echo "process started" - trap trap_handler SIGINT - echo "trap installed" - - sleep 10 - echo "exit normally" - """ - ) - - let observability = ObservabilitySystem.makeForTesting() - let cancellator = Cancellator(observabilityScope: observability.topScope) + #if os(macOS) + try withTemporaryDirectory { temporaryDirectory in + let scriptPath = temporaryDirectory.appending("script") + try localFileSystem.writeFileContents( + scriptPath, + string: """ + set -e + + trap_handler() { + echo "SIGINT trap" + sleep 10 + echo "exit SIGINT trap" + } + + echo "process started" + trap trap_handler SIGINT + echo "trap installed" + + sleep 10 + echo "exit normally" + """ + ) - // outputRedirection used to signal that the process SIGINT traps have been set up - let startSemaphore = ProcessStartedSemaphore(term: "trap installed") - let process = AsyncProcess( - arguments: ["bash", scriptPath.pathString], - outputRedirection: .stream( - stdout: startSemaphore.handleOutput, - stderr: startSemaphore.handleOutput + let observability = ObservabilitySystem.makeForTesting() + let cancellator = Cancellator(observabilityScope: observability.topScope) + + // outputRedirection used to signal that the process SIGINT traps have been set up + let startSemaphore = ProcessStartedSemaphore(term: "trap installed") + let process = AsyncProcess( + arguments: ["bash", scriptPath.pathString], + outputRedirection: .stream( + stdout: startSemaphore.handleOutput, + stderr: startSemaphore.handleOutput + ) ) - ) - let registrationKey = cancellator.register(process) - XCTAssertNotNil(registrationKey) - - let finishSemaphore = DispatchSemaphore(value: 0) - DispatchQueue.sharedConcurrent.async { - defer { finishSemaphore.signal() } - do { - try process.launch() - let result = try process.waitUntilExit() - print("process finished") - XCTAssertEqual(result.exitStatus, .signalled(signal: SIGKILL)) - } catch { - XCTFail("failed launching process: \(error)") + let registrationKey = cancellator.register(process) + XCTAssertNotNil(registrationKey) + + let finishSemaphore = DispatchSemaphore(value: 0) + DispatchQueue.sharedConcurrent.async { + defer { finishSemaphore.signal() } + do { + try process.launch() + let result = try process.waitUntilExit() + print("process finished") + XCTAssertEqual(result.exitStatus, .signalled(signal: SIGKILL)) + } catch { + XCTFail("failed launching process: \(error)") + } } - } - XCTAssertEqual(.success, startSemaphore.wait(timeout: .now() + .seconds(5)), "timeout starting tasks") - print("process started") + XCTAssertEqual(.success, startSemaphore.wait(timeout: .now() + .seconds(5)), "timeout starting tasks") + print("process started") - let cancelled = cancellator._cancel(deadline: .now() + .seconds(1)) - XCTAssertEqual(cancelled, 1) + let cancelled = cancellator._cancel(deadline: .now() + .seconds(1)) + XCTAssertEqual(cancelled, 1) - XCTAssertEqual(.success, finishSemaphore.wait(timeout: .now() + .seconds(5)), "timeout finishing tasks") + XCTAssertEqual(.success, finishSemaphore.wait(timeout: .now() + .seconds(5)), "timeout finishing tasks") - XCTAssertNoDiagnostics(observability.diagnostics) - } -#else - try XCTSkipIf(true, "skipping on non-macOS, signal traps do not work well on docker") -#endif + XCTAssertNoDiagnostics(observability.diagnostics) + } + #else + try XCTSkipIf(true, "skipping on non-macOS, signal traps do not work well on docker") + #endif } func testFoundationProcess() throws { -#if os(macOS) - try withTemporaryDirectory { temporaryDirectory in - let scriptPath = temporaryDirectory.appending("script") - try localFileSystem.writeFileContents( - scriptPath, - string: """ - set -e - - echo "process started" - - sleep 10 - echo "exit normally" - """ - ) - - let observability = ObservabilitySystem.makeForTesting() - let cancellator = Cancellator(observabilityScope: observability.topScope) - - // pipe used to signal that the process started - let startSemaphore = ProcessStartedSemaphore(term: "process started") - let process = Foundation.Process() - process.executableURL = URL(fileURLWithPath: "/bin/bash") - process.arguments = [scriptPath.pathString] - let stdoutPipe = Pipe() - stdoutPipe.fileHandleForReading.readabilityHandler = { fileHandle in - startSemaphore.handleOutput([UInt8](fileHandle.availableData)) - } - let stderrPipe = Pipe() - stderrPipe.fileHandleForReading.readabilityHandler = { fileHandle in - startSemaphore.handleOutput([UInt8](fileHandle.availableData)) - } - process.standardOutput = stdoutPipe - process.standardError = stderrPipe - - let registrationKey = cancellator.register(process) - XCTAssertNotNil(registrationKey) - - let finishSemaphore = DispatchSemaphore(value: 0) + #if os(macOS) + try withTemporaryDirectory { temporaryDirectory in + let scriptPath = temporaryDirectory.appending("script") + try localFileSystem.writeFileContents( + scriptPath, + string: """ + set -e + + echo "process started" + + sleep 10 + echo "exit normally" + """ + ) - DispatchQueue.sharedConcurrent.async { - defer { finishSemaphore.signal() } - do { - try process.run() - } catch { - XCTFail("Process failed to run with error: \(error)") + let observability = ObservabilitySystem.makeForTesting() + let cancellator = Cancellator(observabilityScope: observability.topScope) + + // pipe used to signal that the process started + let startSemaphore = ProcessStartedSemaphore(term: "process started") + let process = Foundation.Process() + process.executableURL = URL(fileURLWithPath: "/bin/bash") + process.arguments = [scriptPath.pathString] + let stdoutPipe = Pipe() + stdoutPipe.fileHandleForReading.readabilityHandler = { fileHandle in + startSemaphore.handleOutput([UInt8](fileHandle.availableData)) } - process.waitUntilExit() - print("process finished") - XCTAssertEqual(process.terminationStatus, SIGINT) - } - - XCTAssertEqual(.success, startSemaphore.wait(timeout: .now() + .seconds(5)), "timeout starting tasks") - print("process started") - - let canncelled = cancellator._cancel(deadline: .now() + .seconds(1)) - XCTAssertEqual(canncelled, 1) - - XCTAssertEqual(.success, finishSemaphore.wait(timeout: .now() + .seconds(5)), "timeout finishing tasks") - print(startSemaphore.output) - - XCTAssertNoDiagnostics(observability.diagnostics) - } -#else - try XCTSkipIf(true, "skipping on non-macOS, signal traps do not work well on docker") -#endif - } - - func testFoundationProcessForceKill() throws { -#if os(macOS) - - try withTemporaryDirectory { temporaryDirectory in - let scriptPath = temporaryDirectory.appending("script") - try localFileSystem.writeFileContents( - scriptPath, - string: """ - set -e - - trap_handler() { - echo "SIGINT trap" - sleep 10 - echo "exit SIGINT trap" + let stderrPipe = Pipe() + stderrPipe.fileHandleForReading.readabilityHandler = { fileHandle in + startSemaphore.handleOutput([UInt8](fileHandle.availableData)) + } + process.standardOutput = stdoutPipe + process.standardError = stderrPipe + + let registrationKey = cancellator.register(process) + XCTAssertNotNil(registrationKey) + + let finishSemaphore = DispatchSemaphore(value: 0) + + DispatchQueue.sharedConcurrent.async { + defer { finishSemaphore.signal() } + do { + try process.run() + } catch { + XCTFail("Process failed to run with error: \(error)") + } + process.waitUntilExit() + print("process finished") + XCTAssertEqual(process.terminationStatus, SIGINT) } - echo "process started" - trap trap_handler SIGINT - echo "trap installed" + XCTAssertEqual(.success, startSemaphore.wait(timeout: .now() + .seconds(5)), "timeout starting tasks") + print("process started") - sleep 10 - echo "exit normally" - """ - ) + let canncelled = cancellator._cancel(deadline: .now() + .seconds(1)) + XCTAssertEqual(canncelled, 1) - let observability = ObservabilitySystem.makeForTesting() - let cancellator = Cancellator(observabilityScope: observability.topScope) - - // pipe used to signal that the process SIGINT traps have been set up - let startSemaphore = ProcessStartedSemaphore(term: "trap installed") - let process = Foundation.Process() - process.executableURL = URL(fileURLWithPath: "/bin/bash") - process.arguments = [scriptPath.pathString] - let stdoutPipe = Pipe() - stdoutPipe.fileHandleForReading.readabilityHandler = { fileHandle in - startSemaphore.handleOutput([UInt8](fileHandle.availableData)) - } - let stderrPipe = Pipe() - stderrPipe.fileHandleForReading.readabilityHandler = { fileHandle in - startSemaphore.handleOutput([UInt8](fileHandle.availableData)) - } - process.standardOutput = stdoutPipe - process.standardError = stderrPipe + XCTAssertEqual(.success, finishSemaphore.wait(timeout: .now() + .seconds(5)), "timeout finishing tasks") + print(startSemaphore.output) - let registrationKey = cancellator.register(process) - XCTAssertNotNil(registrationKey) + XCTAssertNoDiagnostics(observability.diagnostics) + } + #else + try XCTSkipIf(true, "skipping on non-macOS, signal traps do not work well on docker") + #endif + } - let finishSemaphore = DispatchSemaphore(value: 0) + func testFoundationProcessForceKill() throws { + #if os(macOS) + + try withTemporaryDirectory { temporaryDirectory in + let scriptPath = temporaryDirectory.appending("script") + try localFileSystem.writeFileContents( + scriptPath, + string: """ + set -e + + trap_handler() { + echo "SIGINT trap" + sleep 10 + echo "exit SIGINT trap" + } + + echo "process started" + trap trap_handler SIGINT + echo "trap installed" + + sleep 10 + echo "exit normally" + """ + ) - DispatchQueue.sharedConcurrent.async { - defer { finishSemaphore.signal() } - do { - try process.run() - } catch { - XCTFail("Process failed to run with error: \(error)") + let observability = ObservabilitySystem.makeForTesting() + let cancellator = Cancellator(observabilityScope: observability.topScope) + + // pipe used to signal that the process SIGINT traps have been set up + let startSemaphore = ProcessStartedSemaphore(term: "trap installed") + let process = Foundation.Process() + process.executableURL = URL(fileURLWithPath: "/bin/bash") + process.arguments = [scriptPath.pathString] + let stdoutPipe = Pipe() + stdoutPipe.fileHandleForReading.readabilityHandler = { fileHandle in + startSemaphore.handleOutput([UInt8](fileHandle.availableData)) + } + let stderrPipe = Pipe() + stderrPipe.fileHandleForReading.readabilityHandler = { fileHandle in + startSemaphore.handleOutput([UInt8](fileHandle.availableData)) + } + process.standardOutput = stdoutPipe + process.standardError = stderrPipe + + let registrationKey = cancellator.register(process) + XCTAssertNotNil(registrationKey) + + let finishSemaphore = DispatchSemaphore(value: 0) + + DispatchQueue.sharedConcurrent.async { + defer { finishSemaphore.signal() } + do { + try process.run() + } catch { + XCTFail("Process failed to run with error: \(error)") + } + process.waitUntilExit() + print("process finished") + XCTAssertEqual(process.terminationStatus, SIGTERM) } - process.waitUntilExit() - print("process finished") - XCTAssertEqual(process.terminationStatus, SIGTERM) - } - XCTAssertEqual(.success, startSemaphore.wait(timeout: .now() + .seconds(5)), "timeout starting tasks") - print("process started") - print(startSemaphore.output) + XCTAssertEqual(.success, startSemaphore.wait(timeout: .now() + .seconds(5)), "timeout starting tasks") + print("process started") + print(startSemaphore.output) - let cancelled = cancellator._cancel(deadline: .now() + .seconds(1)) - XCTAssertEqual(cancelled, 1) + let cancelled = cancellator._cancel(deadline: .now() + .seconds(1)) + XCTAssertEqual(cancelled, 1) - XCTAssertEqual(.success, finishSemaphore.wait(timeout: .now() + .seconds(5)), "timeout finishing tasks") + XCTAssertEqual(.success, finishSemaphore.wait(timeout: .now() + .seconds(5)), "timeout finishing tasks") - XCTAssertNoDiagnostics(observability.diagnostics) - } -#else - try XCTSkipIf(true, "skipping on non-macOS, signal traps do not work well on docker") -#endif + XCTAssertNoDiagnostics(observability.diagnostics) + } + #else + try XCTSkipIf(true, "skipping on non-macOS, signal traps do not work well on docker") + #endif } func testConcurrency() throws { -#if !os(macOS) - try XCTSkipIf(true, "skipping on non-macOS because of timeout problems") -#endif + #if !os(macOS) + try XCTSkipIf(true, "skipping on non-macOS because of timeout problems") + #endif let observability = ObservabilitySystem.makeForTesting() let cancellator = Cancellator(observabilityScope: observability.topScope) let total = Concurrency.maxOperations - let workers: [Worker] = (0 ..< total).map { index in + let workers: [Worker] = (0..() try await withThrowingTaskGroup(of: Void.self) { group in - for index in 0 ..< 1000 { + for index in 0..<1000 { group.addTask { - try await Task.sleep(nanoseconds: UInt64(Double.random(in: 100 ... 300) * 1000)) - let value = Int.random(in: Int.min ..< Int.max) + try await Task.sleep(nanoseconds: UInt64(Double.random(in: 100...300) * 1000)) + let value = Int.random(in: Int.min..() try await withThrowingTaskGroup(of: Void.self) { group in - for _ in 0 ..< 1000 { + for _ in 0..<1000 { group.addTask { - try await Task.sleep(nanoseconds: UInt64(Double.random(in: 100 ... 300) * 1000)) - let value = Int.random(in: Int.min ..< Int.max) + try await Task.sleep(nanoseconds: UInt64(Double.random(in: 100...300) * 1000)) + let value = Int.random(in: Int.min..() let coordinator = SerialCoordinator() try await withThrowingTaskGroup(of: Void.self) { group in - for index in 0 ..< 1000 { + for index in 0..<1000 { group.addTask { // Random sleep to simulate concurrent access timing - try await Task.sleep(nanoseconds: UInt64(Double.random(in: 100 ... 300) * 1000)) + try await Task.sleep(nanoseconds: UInt64(Double.random(in: 100...300) * 1000)) // Process both winner determination and cache memoization serially await coordinator.processTask(index, winner: &winner, cache: cache) diff --git a/Tests/BasicsTests/Environment/EnvironmentKeyTests.swift b/Tests/BasicsTests/Environment/EnvironmentKeyTests.swift index 7c616de30bb..b96867c8419 100644 --- a/Tests/BasicsTests/Environment/EnvironmentKeyTests.swift +++ b/Tests/BasicsTests/Environment/EnvironmentKeyTests.swift @@ -49,8 +49,8 @@ struct EnvironmentKeyTests { #expect(key0 != key2) #if os(Windows) - // Test case insensitivity on windows - let key3 = EnvironmentKey("teSt") + // Test case insensitivity on windows + let key3 = EnvironmentKey("teSt") #expect(key0 == key3) #endif } @@ -84,8 +84,8 @@ struct EnvironmentKeyTests { #expect(set.insert(key2).inserted) #if os(Windows) - // Test case insensitivity on windows - let key3 = EnvironmentKey("teSt") + // Test case insensitivity on windows + let key3 = EnvironmentKey("teSt") #expect(set.contains(key3)) #expect(!set.insert(key3).inserted) #endif diff --git a/Tests/BasicsTests/Environment/EnvironmentTests.swift b/Tests/BasicsTests/Environment/EnvironmentTests.swift index 7c6978d55ee..a1fb5e655d6 100644 --- a/Tests/BasicsTests/Environment/EnvironmentTests.swift +++ b/Tests/BasicsTests/Environment/EnvironmentTests.swift @@ -11,9 +11,7 @@ //===----------------------------------------------------------------------===// import Foundation -@_spi(SwiftPMInternal) -@testable -import Basics +@_spi(SwiftPMInternal) @testable import Basics import Testing import _InternalTestSupport @@ -121,9 +119,9 @@ struct EnvironmentTests { @Test func current() throws { #if os(Windows) - let pathEnvVarName = "Path" + let pathEnvVarName = "Path" #else - let pathEnvVarName = "PATH" + let pathEnvVarName = "PATH" #endif #expect(Environment.current["PATH"] == ProcessInfo.processInfo.environment[pathEnvVarName]) @@ -172,13 +170,13 @@ struct EnvironmentTests { #expect(environment[key] == nil) try Environment.set(key: key, value: value) - environment = Environment.current // reload + environment = Environment.current // reload #expect(environment[key] == value) try Environment.set(key: key, value: nil) #expect(environment[key] == value) // this is a copy! - environment = Environment.current // reload + environment = Environment.current // reload #expect(environment[key] == nil) } @@ -224,11 +222,11 @@ struct EnvironmentTests { let environment1: Environment = ["TestKey": "TestValue"] #expect(environment0 == environment1) -#if os(Windows) - // Test case insensitivity on windows - let environment2: Environment = ["testKey": "TestValue"] + #if os(Windows) + // Test case insensitivity on windows + let environment2: Environment = ["testKey": "TestValue"] #expect(environment0 == environment2) -#endif + #endif } @Test @@ -237,7 +235,6 @@ struct EnvironmentTests { #expect(environment["TestKey"] == "TestValue") } - @Test func decodable() throws { let jsonString = #"{"TestKey":"TestValue"}"# diff --git a/Tests/BasicsTests/FileSystem/FileSystemTests.swift b/Tests/BasicsTests/FileSystem/FileSystemTests.swift index 270fcc968f8..9a2f8df60fa 100644 --- a/Tests/BasicsTests/FileSystem/FileSystemTests.swift +++ b/Tests/BasicsTests/FileSystem/FileSystemTests.swift @@ -60,8 +60,7 @@ struct FileSystemTests { let functionUnderTest = "stripFirstLevel" do { let fileSystem = InMemoryFileSystem() - #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) - { + #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) { try fileSystem.stripFirstLevel(of: .root) } } @@ -72,8 +71,7 @@ struct FileSystemTests { let path = AbsolutePath.root.appending("dir\(index)") try fileSystem.createDirectory(path, recursive: false) } - #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) - { + #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) { try fileSystem.stripFirstLevel(of: .root) } } @@ -84,8 +82,7 @@ struct FileSystemTests { let path = AbsolutePath.root.appending("file\(index)") try fileSystem.writeFileContents(path, string: "\(index)") } - #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) - { + #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) { try fileSystem.stripFirstLevel(of: .root) } } @@ -94,8 +91,7 @@ struct FileSystemTests { let fileSystem = InMemoryFileSystem() let path = AbsolutePath.root.appending("file") try fileSystem.writeFileContents(path, string: "") - #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) - { + #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) { try fileSystem.stripFirstLevel(of: .root) } } diff --git a/Tests/BasicsTests/FileSystem/InMemoryFilesSystemTests.swift b/Tests/BasicsTests/FileSystem/InMemoryFilesSystemTests.swift index be08df26ab1..5d21e5206f2 100644 --- a/Tests/BasicsTests/FileSystem/InMemoryFilesSystemTests.swift +++ b/Tests/BasicsTests/FileSystem/InMemoryFilesSystemTests.swift @@ -16,9 +16,9 @@ import Testing import _InternalTestSupport #if os(Linux) -let isLinux = true + let isLinux = true #else -let isLinux = false + let isLinux = false #endif @Suite( @@ -90,14 +90,14 @@ struct InMemoryFileSystemTests { let expectedPath = AbsolutePath(p) #expect( fs.exists(expectedPath) == shouldExist, - "\(errorMessage(expectedPath, shouldExist))") + "\(errorMessage(expectedPath, shouldExist))" + ) } } when: { expectError } } - @Test( arguments: [ "/", @@ -138,7 +138,8 @@ struct InMemoryFileSystemTests { // THEN we expect the file to exist #expect( fs.exists(pathUnderTest), - "Path \(pathUnderTest.pathString) does not exists when it should") + "Path \(pathUnderTest.pathString) does not exists when it should" + ) } @Test @@ -158,7 +159,8 @@ struct InMemoryFileSystemTests { // AND we expect the file to not exist #expect( !fs.exists(pathUnderTest), - "Path \(pathUnderTest.pathString) does exists when it should not") + "Path \(pathUnderTest.pathString) does exists when it should not" + ) } @Test @@ -198,7 +200,6 @@ struct InMemoryFileSystemTests { } } - struct testReadFileContentsTests { @Test func readingAFileThatDoesNotExistsRaisesAnError() async throws { @@ -255,8 +256,7 @@ struct InMemoryFileSystemTests { func errorOccursWhenChangingDirectoryDoesNotExists() async throws { // GIVEN we have a filesytstem - let fs = InMemoryFileSystem( - ) + let fs = InMemoryFileSystem() let nonExistingDirectory = AbsolutePath.root.appending(components: "does-not-exists") // WHEN We change directory to this file diff --git a/Tests/BasicsTests/FileSystem/PathShimTests.swift b/Tests/BasicsTests/FileSystem/PathShimTests.swift index 3dc752c2837..06623111866 100644 --- a/Tests/BasicsTests/FileSystem/PathShimTests.swift +++ b/Tests/BasicsTests/FileSystem/PathShimTests.swift @@ -36,30 +36,30 @@ struct PathShimTests { struct WalkTests { @Test func nonRecursive() throws { -#if os(Android) - let root = "/system" - var expected: [AbsolutePath] = [ - "\(root)/usr", - "\(root)/bin", - "\(root)/etc", - ] - let expectedCount = 3 -#elseif os(Windows) - let root = ProcessInfo.processInfo.environment["SystemRoot"]! - var expected: [AbsolutePath] = [ - "\(root)/System32", - "\(root)/SysWOW64", - ] - let expectedCount = (root as NSString).pathComponents.count + 2 -#else - let root = "" - var expected: [AbsolutePath] = [ - "/usr", - "/bin", - "/sbin", - ] - let expectedCount = 2 -#endif + #if os(Android) + let root = "/system" + var expected: [AbsolutePath] = [ + "\(root)/usr", + "\(root)/bin", + "\(root)/etc", + ] + let expectedCount = 3 + #elseif os(Windows) + let root = ProcessInfo.processInfo.environment["SystemRoot"]! + var expected: [AbsolutePath] = [ + "\(root)/System32", + "\(root)/SysWOW64", + ] + let expectedCount = (root as NSString).pathComponents.count + 2 + #else + let root = "" + var expected: [AbsolutePath] = [ + "/usr", + "/bin", + "/sbin", + ] + let expectedCount = 2 + #endif for x in try walk(AbsolutePath(validating: "\(root)/"), recursively: false) { if let i = expected.firstIndex(of: x) { expected.remove(at: i) diff --git a/Tests/BasicsTests/FileSystem/PathTests.swift b/Tests/BasicsTests/FileSystem/PathTests.swift index a4c15dac7de..b19a84f480e 100644 --- a/Tests/BasicsTests/FileSystem/PathTests.swift +++ b/Tests/BasicsTests/FileSystem/PathTests.swift @@ -13,12 +13,11 @@ import Foundation import Testing #if os(Windows) -private var windows: Bool { true } + private var windows: Bool { true } #else -private var windows: Bool { false } + private var windows: Bool { false } #endif - @Suite( .tags( .TestSize.small, @@ -57,7 +56,7 @@ struct PathTests { (path: "/ab//cd//ef", expected: (windows ? #"\ab\cd\ef"# : "/ab/cd/ef"), label: "repeated path seperators"), (path: "/ab///cd//ef", expected: (windows ? #"\ab\cd\ef"# : "/ab/cd/ef"), label: "repeated path seperators"), (path: "/ab/././cd//ef", expected: "/ab/cd/ef", label: "dot path component"), - (path: "/ab/./cd//ef/.", expected: "/ab/cd/ef", label: "dot path component"), + (path: "/ab/./cd//ef/.", expected: "/ab/cd/ef", label: "dot path component"), (path: "/..", expected: (windows ? #"\"# : "/"), label: "dot dot path component"), (path: "/../../../../..", expected: (windows ? #"\"# : "/"), label: "dot dot path component"), (path: "/abc/..", expected: (windows ? #"\"# : "/"), label: "dot dot path component"), @@ -76,7 +75,7 @@ struct PathTests { expected: expected, label: label ) - } when :{ + } when: { ProcessInfo.hostOperatingSystem == .windows } } @@ -153,7 +152,7 @@ struct PathTests { @Test( .IssueWindowsPathTestsFailures, arguments: [ - (path: "/../..", expected: "/"), + (path: "/../..", expected: "/") ] ) func absolutePathBaseNameExtractionFailsOnWindows(path: String, expected: String) throws { @@ -170,16 +169,16 @@ struct PathTests { let actual = AbsolutePath(path).basenameWithoutExt #expect(actual == expected, "Actual is not as expected. Path is: \(path)") - + } @Test( arguments: [ - (path: "/", expected: (windows ? #"\"# : "/")), - (path: "/a", expected: "a"), - (path: "/./a", expected: "a"), - (path: "/a.txt", expected: "a"), - (path: "/./a.txt", expected: "a"), + (path: "/", expected: (windows ? #"\"# : "/")), + (path: "/a", expected: "a"), + (path: "/./a", expected: "a"), + (path: "/a.txt", expected: "a"), + (path: "/./a.txt", expected: "a"), ] ) func absolutePathBaseNameWithoutExt(path: String, expected: String) throws { @@ -189,7 +188,7 @@ struct PathTests { @Test( .IssueWindowsPathTestsFailures, arguments: [ - (path: "/../..", expected: "/"), + (path: "/../..", expected: "/") ] ) func absolutePathBaseNameWithoutExtFailedOnWindows(path: String, expected: String) throws { @@ -208,7 +207,7 @@ struct PathTests { try #require(numParentDirectoryCalls >= 1, "Test configuration Error.") var actual = pathUnderTest - for _ in 0 ..< numParentDirectoryCalls { + for _ in 0..(Date()) let maxAttempts = 5 - let errorCode = Int.random(in: 500 ..< 600) + let errorCode = Int.random(in: 500..<600) let delay = SendableTimeInterval.milliseconds(100) let httpClient = HTTPClient { _, _ in @@ -46,13 +46,12 @@ class HTTPClientXCTest: XCTestCase { } } - struct HTTPClientTests { @Test func head() async throws { let url = URL("http://test") let requestHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) - let responseStatus = Int.random(in: 201 ..< 500) + let responseStatus = Int.random(in: 201..<500) let responseHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) let responseBody: Data? = nil @@ -73,7 +72,7 @@ struct HTTPClientTests { func testGet() async throws { let url = URL("http://test") let requestHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) - let responseStatus = Int.random(in: 201 ..< 500) + let responseStatus = Int.random(in: 201..<500) let responseHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) let responseBody = Data(UUID().uuidString.utf8) @@ -95,7 +94,7 @@ struct HTTPClientTests { let url = URL("http://test") let requestHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) let requestBody = Data(UUID().uuidString.utf8) - let responseStatus = Int.random(in: 201 ..< 500) + let responseStatus = Int.random(in: 201..<500) let responseHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) let responseBody = Data(UUID().uuidString.utf8) @@ -118,7 +117,7 @@ struct HTTPClientTests { let url = URL("http://test") let requestHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) let requestBody = Data(UUID().uuidString.utf8) - let responseStatus = Int.random(in: 201 ..< 500) + let responseStatus = Int.random(in: 201..<500) let responseHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) let responseBody = Data(UUID().uuidString.utf8) @@ -140,7 +139,7 @@ struct HTTPClientTests { func delete() async throws { let url = URL("http://test") let requestHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) - let responseStatus = Int.random(in: 201 ..< 500) + let responseStatus = Int.random(in: 201..<500) let responseHeaders = HTTPClientHeaders([HTTPClientHeaders.Item(name: UUID().uuidString, value: UUID().uuidString)]) let responseBody = Data(UUID().uuidString.utf8) @@ -250,7 +249,7 @@ struct HTTPClientTests { @Test func validResponseCodes() async throws { - let statusCode = Int.random(in: 201 ..< 500) + let statusCode = Int.random(in: 201..<500) let httpClient = HTTPClient { _, _ in throw HTTPClientError.badResponseStatusCode(statusCode) @@ -267,19 +266,19 @@ struct HTTPClientTests { @Test func hostCircuitBreaker() async throws { let maxErrors = 5 - let errorCode = Int.random(in: 500 ..< 600) + let errorCode = Int.random(in: 500..<600) let age = SendableTimeInterval.seconds(5) let host = "http://tes-\(UUID().uuidString).com" let configuration = HTTPClientConfiguration(circuitBreakerStrategy: .hostErrors(maxErrors: maxErrors, age: age)) let httpClient = HTTPClient(configuration: configuration) { _, _ in - .init(statusCode: errorCode) + .init(statusCode: errorCode) } // make the initial errors do { let counter = SendableBox(0) - for index in (0 ..< maxErrors) { + for index in (0..(0) - for index in (0 ..< total) { + for index in (0..(0) let lastCall = ThreadSafeBox() let maxAttempts = 5 - let errorCode = Int.random(in: 500 ..< 600) + let errorCode = Int.random(in: 500..<600) let delay = SendableTimeInterval.milliseconds(100) let brokenHandler: LegacyHTTPClient.Handler = { _, _, completion in @@ -390,7 +390,7 @@ final class LegacyHTTPClientTests: XCTestCase { func testHostCircuitBreaker() { let maxErrors = 5 - let errorCode = Int.random(in: 500 ..< 600) + let errorCode = Int.random(in: 500..<600) let age = SendableTimeInterval.seconds(5) let host = "http://tes-\(UUID().uuidString).com" @@ -403,7 +403,7 @@ final class LegacyHTTPClientTests: XCTestCase { do { let sync = DispatchGroup() let count = ThreadSafeBox(0) - (0 ..< maxErrors).forEach { index in + (0..(0) - let total = Int.random(in: 10 ..< 20) - (0 ..< total).forEach { index in + let total = Int.random(in: 10..<20) + (0..(0) - (0 ..< maxErrors).forEach { index in + (0..(0) - (0 ..< total).forEach { index in + (0.. maxConcurrentRequests { - XCTFail("too many concurrent requests \(concurrentRequests), expected \(maxConcurrentRequests)") + concurrentRequestsLock.withLock { + concurrentRequests += 1 + if concurrentRequests > maxConcurrentRequests { + XCTFail("too many concurrent requests \(concurrentRequests), expected \(maxConcurrentRequests)") + } } - } - completion(.success(.okay())) - }) + completion(.success(.okay())) + } + ) let total = 1000 let sync = DispatchGroup() let results = ThreadSafeArrayStore>() - for _ in 0 ..< total { + for _ in 0..>() - for index in 0 ..< total { + for index in 0.. [String: String] { +private func makeMockData(fileSystem: FileSystem, rootPath: AbsolutePath, count: Int = Int.random(in: 50..<100)) throws -> [String: String] { var data = [String: String]() let value = UUID().uuidString - for index in 0 ..< count { + for index in 0.. (user: String, password: String)? { - self.underlying.authorization(for: url).map{ (user: $0.login, password: $0.password) } + self.underlying.authorization(for: url).map { (user: $0.login, password: $0.password) } } } diff --git a/Tests/BuildTests/BuildOperationTests.swift b/Tests/BuildTests/BuildOperationTests.swift index af243134cb5..27555cff812 100644 --- a/Tests/BuildTests/BuildOperationTests.swift +++ b/Tests/BuildTests/BuildOperationTests.swift @@ -15,11 +15,9 @@ import Basics import LLBuildManifest -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph import SPMBuildCore -@_spi(SwiftPMInternal) -import _InternalTestSupport +@_spi(SwiftPMInternal) import _InternalTestSupport import XCTest import class TSCBasic.BufferedOutputByteStream @@ -61,10 +59,10 @@ final class BuildOperationTests: XCTestCase { displayName: "SwitchTriple", path: "/Pkg", targets: [ - TargetDescription(name: "ATarget"), + TargetDescription(name: "ATarget") ], traits: [] - ), + ) ], observabilityScope: observability.topScope ) @@ -88,7 +86,8 @@ final class BuildOperationTests: XCTestCase { cacheBuildManifest: false, packageGraphLoader: { packageGraph }, scratchDirectory: scratchDirectory, - fs: fs, observabilityScope: observability.topScope + fs: fs, + observabilityScope: observability.topScope ) // Generate initial llbuild manifest let _ = try await buildOp.getBuildDescription() @@ -121,7 +120,8 @@ final class BuildOperationTests: XCTestCase { cacheBuildManifest: true, packageGraphLoader: { packageGraph }, scratchDirectory: scratchDirectory, - fs: fs, observabilityScope: observability.topScope + fs: fs, + observabilityScope: observability.topScope ) // Generate llbuild manifest let _ = try await buildOp.getBuildDescription() @@ -136,7 +136,7 @@ final class BuildOperationTests: XCTestCase { } func testHostProductsAndTargetsWithoutExplicitDestination() async throws { - let mock = try macrosTestsPackageGraph() + let mock = try macrosTestsPackageGraph() let hostParameters = mockBuildParameters(destination: .host) let targetParameters = mockBuildParameters(destination: .target) diff --git a/Tests/BuildTests/BuildPlanTraversalTests.swift b/Tests/BuildTests/BuildPlanTraversalTests.swift index 53ba2fc4d5b..18e9f50197b 100644 --- a/Tests/BuildTests/BuildPlanTraversalTests.swift +++ b/Tests/BuildTests/BuildPlanTraversalTests.swift @@ -198,7 +198,7 @@ struct BuildPlanTraversalTests { #expect(moduleDependencies[0].0.name == "MMIOMacros") #expect(moduleDependencies[1].0.name == "SwiftSyntax") - for index in 0 ..< moduleDependencies.count { + for index in 0.. ClangModuleBuildDescription { + private func makeTargetBuildDescription( + _ packageName: String, + buildParameters: BuildParameters? = nil, + usesSourceControl: Bool = false + ) throws -> ClangModuleBuildDescription { let observability = ObservabilitySystem.makeForTesting(verbose: false) let manifest: Manifest if usesSourceControl { manifest = Manifest.createLocalSourceControlManifest( - displayName: packageName, path: AbsolutePath("/\(packageName)")) + displayName: packageName, + path: AbsolutePath("/\(packageName)") + ) } else { manifest = Manifest.createRootManifest( displayName: packageName, toolsVersion: .v5, - targets: [try TargetDescription(name: "dummy")]) + targets: [try TargetDescription(name: "dummy")] + ) } let target = try makeResolvedTarget() - let package = Package(identity: .plain(packageName), - manifest: manifest, - path: .root, - targets: [target.underlying], - products: [], - targetSearchPath: .root, - testTargetSearchPath: .root) + let package = Package( + identity: .plain(packageName), + manifest: manifest, + path: .root, + targets: [target.underlying], + products: [], + targetSearchPath: .root, + testTargetSearchPath: .root + ) return try ClangModuleBuildDescription( - package: .init(underlying: package, - defaultLocalization: nil, - supportedPlatforms: [], - dependencies: [], - enabledTraits: [], - modules: .init([target]), - products: [], - registryMetadata: nil, - platformVersionProvider: .init(implementation: .minimumDeploymentTargetDefault)), + package: .init( + underlying: package, + defaultLocalization: nil, + supportedPlatforms: [], + dependencies: [], + enabledTraits: [], + modules: .init([target]), + products: [], + registryMetadata: nil, + platformVersionProvider: .init(implementation: .minimumDeploymentTargetDefault) + ), target: target, toolsVersion: .current, - buildParameters: buildParameters ?? mockBuildParameters( - destination: .target, - toolchain: try UserToolchain.default, - indexStoreMode: .on - ), + buildParameters: buildParameters + ?? mockBuildParameters( + destination: .target, + toolchain: try UserToolchain.default, + indexStoreMode: .on + ), fileSystem: localFileSystem, observabilityScope: observability.topScope ) diff --git a/Tests/BuildTests/CrossCompilationBuildPlanTests.swift b/Tests/BuildTests/CrossCompilationBuildPlanTests.swift index 0388f0ad0aa..804489c8b22 100644 --- a/Tests/BuildTests/CrossCompilationBuildPlanTests.swift +++ b/Tests/BuildTests/CrossCompilationBuildPlanTests.swift @@ -49,13 +49,15 @@ final class CrossCompilationBuildPlanTests: XCTestCase { shouldLinkStaticSwiftStdlib: true ) - var result = try await BuildPlanResult(plan: mockBuildPlan( - triple: triple, - graph: graph, - linkingParameters: linkingParameters, - fileSystem: fs, - observabilityScope: observabilityScope - )) + var result = try await BuildPlanResult( + plan: mockBuildPlan( + triple: triple, + graph: graph, + linkingParameters: linkingParameters, + fileSystem: fs, + observabilityScope: observabilityScope + ) + ) result.checkProductsCount(2) // There are two additional modules on non-Apple platforms, for test discovery and // test entry point @@ -78,13 +80,15 @@ final class CrossCompilationBuildPlanTests: XCTestCase { (graph, fs, observabilityScope) = try embeddedCxxInteropPackageGraph() - result = try await BuildPlanResult(plan: mockBuildPlan( - triple: triple, - graph: graph, - linkingParameters: linkingParameters, - fileSystem: fs, - observabilityScope: observabilityScope - )) + result = try await BuildPlanResult( + plan: mockBuildPlan( + triple: triple, + graph: graph, + linkingParameters: linkingParameters, + fileSystem: fs, + observabilityScope: observabilityScope + ) + ) result.checkProductsCount(2) // There are two additional modules on non-Apple platforms, for test discovery and // test entry point @@ -109,17 +113,19 @@ final class CrossCompilationBuildPlanTests: XCTestCase { func testWasmTargetRelease() async throws { let (graph, fs, observabilityScope) = try trivialPackageGraph() - let result = try await BuildPlanResult(plan: mockBuildPlan( - config: .release, - triple: .wasi, - graph: graph, - linkingParameters: .init( - linkerDeadStrip: true, - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observabilityScope - )) + let result = try await BuildPlanResult( + plan: mockBuildPlan( + config: .release, + triple: .wasi, + graph: graph, + linkingParameters: .init( + linkerDeadStrip: true, + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observabilityScope + ) + ) let buildPath = result.plan.productsBuildPath let appBuildDescription = try result.buildProduct(for: "app") @@ -143,15 +149,17 @@ final class CrossCompilationBuildPlanTests: XCTestCase { let (graph, fs, observabilityScope) = try trivialPackageGraph() - let result = try await BuildPlanResult(plan: mockBuildPlan( - triple: .wasi, - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observabilityScope - )) + let result = try await BuildPlanResult( + plan: mockBuildPlan( + triple: .wasi, + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observabilityScope + ) + ) result.checkProductsCount(2) // There are two additional modules on non-Apple platforms, for test discovery and // test entry point @@ -165,13 +173,16 @@ final class CrossCompilationBuildPlanTests: XCTestCase { .first { $0.destination == .target } ) - XCTAssertEqual(try lib.basicArguments(isCXX: false), [ - "-target", "wasm32-unknown-wasi", - "-O0", "-DSWIFT_PACKAGE=1", "-DDEBUG=1", - "-fblocks", - "-I", pkgPath.appending(components: "Sources", "lib", "include").pathString, - "-g", - ]) + XCTAssertEqual( + try lib.basicArguments(isCXX: false), + [ + "-target", "wasm32-unknown-wasi", + "-O0", "-DSWIFT_PACKAGE=1", "-DDEBUG=1", + "-fblocks", + "-I", pkgPath.appending(components: "Sources", "lib", "include").pathString, + "-g", + ] + ) XCTAssertEqual(try lib.objects, [buildPath.appending(components: "lib.build", "lib.c.o")]) XCTAssertEqual(lib.moduleMap, buildPath.appending(components: "lib.build", "module.modulemap")) @@ -247,9 +258,11 @@ final class CrossCompilationBuildPlanTests: XCTestCase { result.checkProductsCount(3) result.checkTargetsCount(10) - XCTAssertTrue(try result.allTargets(named: "SwiftSyntax") - .map { try $0.swift() } - .contains { $0.destination == .host }) + XCTAssertTrue( + try result.allTargets(named: "SwiftSyntax") + .map { try $0.swift() } + .contains { $0.destination == .host } + ) try result.check(destination: .host, triple: toolsTriple, for: "MMIOMacros") try result.check(destination: .target, triple: destinationTriple, for: "MMIO") try result.check(destination: .target, triple: destinationTriple, for: "Core") @@ -271,7 +284,7 @@ final class CrossCompilationBuildPlanTests: XCTestCase { .anySequence, "-Xfrontend", "-load-plugin-executable", // Verify that macros are located in the tools triple directory. - "-Xfrontend", .contains(toolsTriple.tripleString) + "-Xfrontend", .contains(toolsTriple.tripleString), ] ) } @@ -308,9 +321,11 @@ final class CrossCompilationBuildPlanTests: XCTestCase { result.checkProductsCount(3) result.checkTargetsCount(20) - XCTAssertTrue(try result.allTargets(named: "SwiftSyntax") - .map { try $0.swift() } - .contains { $0.destination == .host }) + XCTAssertTrue( + try result.allTargets(named: "SwiftSyntax") + .map { try $0.swift() } + .contains { $0.destination == .host } + ) try result.check(destination: .host, triple: toolsTriple, for: "swift-mmioPackageTests") try result.check(destination: .host, triple: toolsTriple, for: "swift-mmioPackageDiscoveredTests") @@ -335,7 +350,7 @@ final class CrossCompilationBuildPlanTests: XCTestCase { .anySequence, "-Xfrontend", "-load-plugin-executable", // Verify that macros are located in the tools triple directory. - "-Xfrontend", .contains(toolsTriple.tripleString) + "-Xfrontend", .contains(toolsTriple.tripleString), ] ) } @@ -364,9 +379,11 @@ final class CrossCompilationBuildPlanTests: XCTestCase { result.checkProductsCount(4) result.checkTargetsCount(6) - XCTAssertTrue(try result.allTargets(named: "SwiftSyntax") - .map { try $0.swift() } - .contains { $0.destination == .host }) + XCTAssertTrue( + try result.allTargets(named: "SwiftSyntax") + .map { try $0.swift() } + .contains { $0.destination == .host } + ) try result.check(destination: .host, triple: toolsTriple, for: "swift-mmioPackageTests") try result.check(destination: .host, triple: toolsTriple, for: "swift-mmioPackageDiscoveredTests") diff --git a/Tests/BuildTests/IncrementalBuildTests.swift b/Tests/BuildTests/IncrementalBuildTests.swift index 0e495269ff2..ed9f9361e34 100644 --- a/Tests/BuildTests/IncrementalBuildTests.swift +++ b/Tests/BuildTests/IncrementalBuildTests.swift @@ -109,7 +109,7 @@ final class IncrementalBuildTests: XCTestCase { XCTAssertMatch(log1, .contains("Compiling Library")) // Ensure manifest caching kicks in. - let log2 = try await build() + let log2 = try await build() XCTAssertMatch(log2, .contains("Planning build")) // Check that we're not re-planning when nothing has changed. @@ -153,30 +153,30 @@ final class IncrementalBuildTests: XCTestCase { } // testing the fix for tracking SDK dependencies to avoid triggering rebuilds when the SDK changes (rdar://115777026) func testSDKTracking() async throws { -#if os(macOS) - try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test") - - try await fixtureXCTest(name: "ValidLayouts/SingleModule/Library") { fixturePath in - let dummySwiftcPath = SwiftPM.xctestBinaryPath(for: "dummy-swiftc") - let swiftCompilerPath = try UserToolchain.default.swiftCompilerPath - let environment: Environment = [ - "SWIFT_EXEC": dummySwiftcPath.pathString, - "SWIFT_ORIGINAL_PATH": swiftCompilerPath.pathString - ] - let sdkPathStr = try await AsyncProcess.checkNonZeroExit( - arguments: ["/usr/bin/xcrun", "--sdk", "macosx", "--show-sdk-path"], - environment: environment - ).spm_chomp() - - let newSdkPathStr = "/tmp/../\(sdkPathStr)" - // Perform a full build again because SDK changed. - let log1 = try await executeSwiftBuild( - fixturePath, - env: ["SDKROOT": newSdkPathStr], - buildSystem: .native, - ).stdout - XCTAssertMatch(log1, .contains("Compiling Library")) - } -#endif + #if os(macOS) + try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test") + + try await fixtureXCTest(name: "ValidLayouts/SingleModule/Library") { fixturePath in + let dummySwiftcPath = SwiftPM.xctestBinaryPath(for: "dummy-swiftc") + let swiftCompilerPath = try UserToolchain.default.swiftCompilerPath + let environment: Environment = [ + "SWIFT_EXEC": dummySwiftcPath.pathString, + "SWIFT_ORIGINAL_PATH": swiftCompilerPath.pathString, + ] + let sdkPathStr = try await AsyncProcess.checkNonZeroExit( + arguments: ["/usr/bin/xcrun", "--sdk", "macosx", "--show-sdk-path"], + environment: environment + ).spm_chomp() + + let newSdkPathStr = "/tmp/../\(sdkPathStr)" + // Perform a full build again because SDK changed. + let log1 = try await executeSwiftBuild( + fixturePath, + env: ["SDKROOT": newSdkPathStr], + buildSystem: .native, + ).stdout + XCTAssertMatch(log1, .contains("Compiling Library")) + } + #endif } } diff --git a/Tests/BuildTests/LLBuildManifestBuilderTests.swift b/Tests/BuildTests/LLBuildManifestBuilderTests.swift index f2bf17e5663..748e490f9b6 100644 --- a/Tests/BuildTests/LLBuildManifestBuilderTests.swift +++ b/Tests/BuildTests/LLBuildManifestBuilderTests.swift @@ -15,15 +15,13 @@ import Basics @testable import Build import LLBuildManifest -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph import PackageModel import struct SPMBuildCore.BuildParameters import _InternalBuildTestSupport -@_spi(SwiftPMInternal) -import _InternalTestSupport +@_spi(SwiftPMInternal) import _InternalTestSupport import Testing @@ -44,9 +42,9 @@ struct LLBuildManifestBuilderTests { displayName: "Pkg", path: .init(validating: pkg.pathString), targets: [ - TargetDescription(name: "exe"), + TargetDescription(name: "exe") ] - ), + ) ], observabilityScope: observability.topScope ) @@ -106,23 +104,30 @@ struct LLBuildManifestBuilderTests { "C.exe-\(plan.destinationBuildParameters.triple)-debug.exe", ] - #expect(llbuild.manifest.commands.map(\.key).sorted() == (basicDebugCommandNames + [ - AbsolutePath("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/exe-entitlement.plist").pathString, - entitlementsCommandName, - ]).sorted()) + #expect( + llbuild.manifest.commands.map(\.key).sorted() + == (basicDebugCommandNames + [ + AbsolutePath("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/exe-entitlement.plist").pathString, + entitlementsCommandName, + ]).sorted() + ) let entitlementsCommand = try #require( llbuild.manifest.commands[entitlementsCommandName]?.tool as? ShellTool, "unexpected entitlements command type" ) - #expect(entitlementsCommand.inputs == [ - .file("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/exe", isMutated: true), - .file("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/exe-entitlement.plist"), - ]) - #expect(entitlementsCommand.outputs == [ - .virtual("exe-\(plan.destinationBuildParameters.triple)-debug.exe-CodeSigning"), - ]) + #expect( + entitlementsCommand.inputs == [ + .file("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/exe", isMutated: true), + .file("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/exe-entitlement.plist"), + ] + ) + #expect( + entitlementsCommand.outputs == [ + .virtual("exe-\(plan.destinationBuildParameters.triple)-debug.exe-CodeSigning") + ] + ) // Linux, release build diff --git a/Tests/BuildTests/ModuleAliasingBuildTests.swift b/Tests/BuildTests/ModuleAliasingBuildTests.swift index 8fdef715f6c..7eb9e524ec8 100644 --- a/Tests/BuildTests/ModuleAliasingBuildTests.swift +++ b/Tests/BuildTests/ModuleAliasingBuildTests.swift @@ -13,8 +13,7 @@ import Basics @testable import Build -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -@testable import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) @testable import PackageGraph import PackageLoading @testable import PackageModel @@ -30,7 +29,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingEmptyAlias() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/fooPkg/Sources/Logging/fileLogging.swift" ) @@ -43,27 +42,29 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "fooPkg", path: "/fooPkg", products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createRootManifest( displayName: "thisPkg", path: "/thisPkg", dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "exe", - dependencies: ["Logging", - .product( - name: "Foo", - package: "fooPkg", - moduleAliases: ["Logging": ""] - )] + dependencies: [ + "Logging", + .product( + name: "Foo", + package: "fooPkg", + moduleAliases: ["Logging": ""] + ), + ] ), TargetDescription(name: "Logging", dependencies: []), ] @@ -80,7 +81,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingInvalidIdentifierAlias() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/fooPkg/Sources/Logging/fileLogging.swift" ) @@ -93,27 +94,29 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "fooPkg", path: "/fooPkg", products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createRootManifest( displayName: "thisPkg", path: "/thisPkg", dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "exe", - dependencies: ["Logging", - .product( - name: "Foo", - package: "fooPkg", - moduleAliases: ["Logging": "P$0%^#@"] - )] + dependencies: [ + "Logging", + .product( + name: "Foo", + package: "fooPkg", + moduleAliases: ["Logging": "P$0%^#@"] + ), + ] ), TargetDescription(name: "Logging", dependencies: []), ] @@ -133,7 +136,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingDuplicateProductNames() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/fooPkg/Sources/Logging/fileLogging.swift", "/barPkg/Sources/Logging/fileLogging.swift" ) @@ -145,20 +148,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "fooPkg", path: "/fooPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "barPkg", path: "/barPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createRootManifest( @@ -172,31 +175,35 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "exe", - dependencies: [.product( - name: "Logging", - package: "fooPkg" - ), - .product( - name: "Logging", - package: "barPkg", - moduleAliases: ["Logging": "BarLogging"] - )], + dependencies: [ + .product( + name: "Logging", + package: "fooPkg" + ), + .product( + name: "Logging", + package: "barPkg", + moduleAliases: ["Logging": "BarLogging"] + ), + ], type: .executable - ), + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(3) XCTAssertTrue( @@ -214,59 +221,63 @@ final class ModuleAliasingBuildTests: XCTestCase { let barPkg: AbsolutePath = "/barPkg" let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/fooPkg/Sources/Logging/fileLogging.swift", "/barPkg/Sources/Logging/fileLogging.swift" ) let observability = ObservabilitySystem.makeForTesting() - XCTAssertThrowsError(try loadModulesGraph( - fileSystem: fs, - manifests: [ - Manifest.createFileSystemManifest( - displayName: "fooPkg", - path: fooPkg, - products: [ - ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]), - ], - targets: [ - TargetDescription(name: "Logging", dependencies: []), - ] - ), - Manifest.createFileSystemManifest( - displayName: "barPkg", - path: barPkg, - products: [ - ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]), - ], - targets: [ - TargetDescription(name: "Logging", dependencies: []), - ] - ), - Manifest.createRootManifest( - displayName: "thisPkg", - path: "/thisPkg", - dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), - .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "2.0.0")), - ], - targets: [ - TargetDescription( - name: "exe", - dependencies: [.product( - name: "Logging", - package: "fooPkg" - ), - .product( - name: "Logging", - package: "barPkg", - moduleAliases: ["Logging": "BarLogging"] - )] - ), - ] - ), - ], - observabilityScope: observability.topScope - )) { error in + XCTAssertThrowsError( + try loadModulesGraph( + fileSystem: fs, + manifests: [ + Manifest.createFileSystemManifest( + displayName: "fooPkg", + path: fooPkg, + products: [ + ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]) + ], + targets: [ + TargetDescription(name: "Logging", dependencies: []) + ] + ), + Manifest.createFileSystemManifest( + displayName: "barPkg", + path: barPkg, + products: [ + ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]) + ], + targets: [ + TargetDescription(name: "Logging", dependencies: []) + ] + ), + Manifest.createRootManifest( + displayName: "thisPkg", + path: "/thisPkg", + dependencies: [ + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "2.0.0")), + ], + targets: [ + TargetDescription( + name: "exe", + dependencies: [ + .product( + name: "Logging", + package: "fooPkg" + ), + .product( + name: "Logging", + package: "barPkg", + moduleAliases: ["Logging": "BarLogging"] + ), + ] + ) + ] + ), + ], + observabilityScope: observability.topScope + ) + ) { error in XCTAssertEqual((error as? PackageGraphError)?.description, "multiple packages (\'barpkg\' (at '\(barPkg)'), \'foopkg\' (at '\(fooPkg)')) declare products with a conflicting name: \'Logging’; product names need to be unique across the package graph") } } @@ -276,59 +287,63 @@ final class ModuleAliasingBuildTests: XCTestCase { let barPkg: AbsolutePath = "/barPkg" let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/fooPkg/Sources/Logging/fileLogging.swift", "/barPkg/Sources/Logging/fileLogging.swift" ) let observability = ObservabilitySystem.makeForTesting() - XCTAssertThrowsError(try loadModulesGraph( - fileSystem: fs, - manifests: [ - Manifest.createFileSystemManifest( - displayName: "fooPkg", - path: fooPkg, - products: [ - ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]), - ], - targets: [ - TargetDescription(name: "Logging", dependencies: []), - ] - ), - Manifest.createFileSystemManifest( - displayName: "barPkg", - path: barPkg, - products: [ - ProductDescription(name: "Logging", type: .library(.static), targets: ["Logging"]), - ], - targets: [ - TargetDescription(name: "Logging", dependencies: []), - ] - ), - Manifest.createRootManifest( - displayName: "thisPkg", - path: "/thisPkg", - dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), - .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "2.0.0")), - ], - targets: [ - TargetDescription( - name: "exe", - dependencies: [.product( - name: "Logging", - package: "fooPkg" - ), - .product( - name: "Logging", - package: "barPkg", - moduleAliases: ["Logging": "BarLogging"] - )] - ), - ] - ), - ], - observabilityScope: observability.topScope - )) { error in + XCTAssertThrowsError( + try loadModulesGraph( + fileSystem: fs, + manifests: [ + Manifest.createFileSystemManifest( + displayName: "fooPkg", + path: fooPkg, + products: [ + ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]) + ], + targets: [ + TargetDescription(name: "Logging", dependencies: []) + ] + ), + Manifest.createFileSystemManifest( + displayName: "barPkg", + path: barPkg, + products: [ + ProductDescription(name: "Logging", type: .library(.static), targets: ["Logging"]) + ], + targets: [ + TargetDescription(name: "Logging", dependencies: []) + ] + ), + Manifest.createRootManifest( + displayName: "thisPkg", + path: "/thisPkg", + dependencies: [ + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "2.0.0")), + ], + targets: [ + TargetDescription( + name: "exe", + dependencies: [ + .product( + name: "Logging", + package: "fooPkg" + ), + .product( + name: "Logging", + package: "barPkg", + moduleAliases: ["Logging": "BarLogging"] + ), + ] + ) + ] + ), + ], + observabilityScope: observability.topScope + ) + ) { error in XCTAssertEqual((error as? PackageGraphError)?.description, "multiple packages (\'barpkg\' (at '\(barPkg)'), \'foopkg\' (at '\(fooPkg)')) declare products with a conflicting name: \'Logging’; product names need to be unique across the package graph") } } @@ -336,7 +351,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingDuplicateDylibAutomaticProductNames() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/fooPkg/Sources/Logging/fileLogging.swift", "/barPkg/Sources/Logging/fileLogging.swift", "/bazPkg/Sources/Logging/fileLogging.swift" @@ -349,20 +364,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "fooPkg", path: "/fooPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "barPkg", path: "/barPkg", products: [ - ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createRootManifest( @@ -376,31 +391,35 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "exe", - dependencies: [.product( - name: "Logging", - package: "fooPkg" - ), - .product( - name: "Logging", - package: "barPkg", - moduleAliases: ["Logging": "BarLogging"] - )], + dependencies: [ + .product( + name: "Logging", + package: "fooPkg" + ), + .product( + name: "Logging", + package: "barPkg", + moduleAliases: ["Logging": "BarLogging"] + ), + ], type: .executable - ), + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(2) result.checkTargetsCount(3) XCTAssertTrue( @@ -412,18 +431,19 @@ final class ModuleAliasingBuildTests: XCTestCase { .contains { $0.module.name == "BarLogging" && $0.module.moduleAliases?["Logging"] == "BarLogging" } ) #if os(macOS) - let dylib = try result.buildProduct(for: "Logging") - XCTAssertTrue( - try dylib.binaryPath.basename == "libLogging.dylib" && dylib.package.identity - .description == "barpkg" - ) + let dylib = try result.buildProduct(for: "Logging") + XCTAssertTrue( + try dylib.binaryPath.basename == "libLogging.dylib" + && dylib.package.identity + .description == "barpkg" + ) #endif } func testModuleAliasingDuplicateStaticLibAutomaticProductNames() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/fooPkg/Sources/Logging/fileLogging.swift", "/bazPkg/Sources/Logging/fileLogging.swift" ) @@ -435,20 +455,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "fooPkg", path: "/fooPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "bazPkg", path: "/bazPkg", products: [ - ProductDescription(name: "Logging", type: .library(.static), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.static), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createRootManifest( @@ -462,31 +482,35 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "exe", - dependencies: [.product( - name: "Logging", - package: "fooPkg" - ), - .product( - name: "Logging", - package: "bazPkg", - moduleAliases: ["Logging": "BazLogging"] - )], + dependencies: [ + .product( + name: "Logging", + package: "fooPkg" + ), + .product( + name: "Logging", + package: "bazPkg", + moduleAliases: ["Logging": "BazLogging"] + ), + ], type: .executable - ), + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(2) result.checkTargetsCount(3) XCTAssertTrue( @@ -498,18 +522,19 @@ final class ModuleAliasingBuildTests: XCTestCase { .contains { $0.module.name == "BazLogging" && $0.module.moduleAliases?["Logging"] == "BazLogging" } ) #if os(macOS) - let staticlib = try result.buildProduct(for: "Logging") - XCTAssertTrue( - try staticlib.binaryPath.basename == "libLogging.a" && staticlib.package.identity - .description == "bazpkg" - ) + let staticlib = try result.buildProduct(for: "Logging") + XCTAssertTrue( + try staticlib.binaryPath.basename == "libLogging.a" + && staticlib.package.identity + .description == "bazpkg" + ) #endif } func testModuleAliasingDuplicateProductNamesUpstream() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/aPkg/Sources/A/file.swift", "/xPkg/Sources/Logging/fileLogging.swift", "/bPkg/Sources/B/file.swift", @@ -523,62 +548,62 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "xPkg", path: "/xPkg", products: [ - ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.dynamic), targets: ["Logging"]) ], targets: [ TargetDescription( name: "Logging", dependencies: [] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "yPkg", path: "/yPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ TargetDescription( name: "Logging", dependencies: [] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "aPkg", path: "/aPkg", dependencies: [ - .localSourceControl(path: "/xPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/xPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "A", type: .library(.dynamic), targets: ["A"]), + ProductDescription(name: "A", type: .library(.dynamic), targets: ["A"]) ], targets: [ TargetDescription( name: "A", dependencies: [ - .product(name: "Logging", package: "xPkg"), + .product(name: "Logging", package: "xPkg") ] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "bPkg", path: "/bPkg", dependencies: [ - .localSourceControl(path: "/yPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/yPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "B", type: .library(.dynamic), targets: ["B"]), + ProductDescription(name: "B", type: .library(.dynamic), targets: ["B"]) ], targets: [ TargetDescription( name: "B", dependencies: [ - .product(name: "Logging", package: "yPkg"), + .product(name: "Logging", package: "yPkg") ] - ), + ) ] ), Manifest.createRootManifest( @@ -591,30 +616,34 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "exe", - dependencies: [.product( - name: "A", - package: "aPkg", - moduleAliases: ["Logging": "ALogging"] - ), - .product( - name: "B", - package: "bPkg" - )] - ), + dependencies: [ + .product( + name: "A", + package: "aPkg", + moduleAliases: ["Logging": "ALogging"] + ), + .product( + name: "B", + package: "bPkg" + ), + ] + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(4) result.checkTargetsCount(5) XCTAssertTrue( @@ -631,18 +660,19 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertTrue(result.targetMap.values.contains { $0.module.name == "B" && $0.module.moduleAliases == nil }) #if os(macOS) - let dylib = try result.buildProduct(for: "Logging") - XCTAssertTrue( - try dylib.binaryPath.basename == "libLogging.dylib" && dylib.package.identity - .description == "xpkg" - ) + let dylib = try result.buildProduct(for: "Logging") + XCTAssertTrue( + try dylib.binaryPath.basename == "libLogging.dylib" + && dylib.package.identity + .description == "xpkg" + ) #endif } func testModuleAliasingDirectDeps() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/fooPkg/Sources/Logging/fileLogging.swift", "/barPkg/Sources/Logging/fileLogging.swift" @@ -656,20 +686,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "fooPkg", path: "/fooPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "barPkg", path: "/barPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createRootManifest( @@ -683,17 +713,19 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "exe", - dependencies: ["Logging", - .product( - name: "Logging", - package: "fooPkg", - moduleAliases: ["Logging": "FooLogging"] - ), - .product( - name: "Logging", - package: "barPkg", - moduleAliases: ["Logging": "BarLogging"] - )], + dependencies: [ + "Logging", + .product( + name: "Logging", + package: "fooPkg", + moduleAliases: ["Logging": "FooLogging"] + ), + .product( + name: "Logging", + package: "barPkg", + moduleAliases: ["Logging": "BarLogging"] + ), + ], type: .executable ), TargetDescription(name: "Logging", dependencies: []), @@ -705,14 +737,16 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(4) @@ -737,28 +771,34 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertMatch( fooLoggingArgs, - [.anySequence, "-emit-objc-header", "-emit-objc-header-path", - "\(buildPath.appending(components: "FooLogging.build", "include", "FooLogging-Swift.h"))", - .anySequence] + [ + .anySequence, "-emit-objc-header", "-emit-objc-header-path", + "\(buildPath.appending(components: "FooLogging.build", "include", "FooLogging-Swift.h"))", + .anySequence, + ] ) XCTAssertMatch( barLoggingArgs, - [.anySequence, "-emit-objc-header", "-emit-objc-header-path", - "\(buildPath.appending(components: "BarLogging.build", "include", "BarLogging-Swift.h"))", - .anySequence] + [ + .anySequence, "-emit-objc-header", "-emit-objc-header-path", + "\(buildPath.appending(components: "BarLogging.build", "include", "BarLogging-Swift.h"))", + .anySequence, + ] ) XCTAssertMatch( loggingArgs, - [.anySequence, "-emit-objc-header", "-emit-objc-header-path", - "\(buildPath.appending(components: "Logging.build", "include", "Logging-Swift.h"))", - .anySequence] + [ + .anySequence, "-emit-objc-header", "-emit-objc-header-path", + "\(buildPath.appending(components: "Logging.build", "include", "Logging-Swift.h"))", + .anySequence, + ] ) } func testModuleAliasingDuplicateTargetNameInUpstream() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/otherPkg/Sources/Utils/fileUtils.swift", "/otherPkg/Sources/Logging/fileLogging.swift", @@ -788,21 +828,23 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "thisPkg", path: "/thisPkg", dependencies: [ - .localSourceControl(path: "/otherPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/otherPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "exe", - dependencies: ["Logging", - .product( - name: "Math", - package: "otherPkg" - ), - .product( - name: "Utils", - package: "otherPkg", - moduleAliases: ["Logging": "OtherLogging"] - )] + dependencies: [ + "Logging", + .product( + name: "Math", + package: "otherPkg" + ), + .product( + name: "Utils", + package: "otherPkg", + moduleAliases: ["Logging": "OtherLogging"] + ), + ] ), TargetDescription(name: "Logging", dependencies: []), ] @@ -812,14 +854,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(6) @@ -843,75 +887,82 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertMatch( otherLoggingArgs, - [.anySequence, "-emit-objc-header", "-emit-objc-header-path", - "\(buildPath.appending(components: "OtherLogging.build", "include", "OtherLogging-Swift.h"))", - .anySequence] + [ + .anySequence, "-emit-objc-header", "-emit-objc-header-path", + "\(buildPath.appending(components: "OtherLogging.build", "include", "OtherLogging-Swift.h"))", + .anySequence, + ] ) XCTAssertMatch( loggingArgs, - [.anySequence, "-emit-objc-header", "-emit-objc-header-path", - "\(buildPath.appending(components: "Logging.build", "include", "Logging-Swift.h"))", - .anySequence] + [ + .anySequence, "-emit-objc-header", "-emit-objc-header-path", + "\(buildPath.appending(components: "Logging.build", "include", "Logging-Swift.h"))", + .anySequence, + ] ) } func testModuleAliasingMultipleAliasesInProduct() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/otherPkg/Sources/Utils/fileUtils.swift", "/otherPkg/Sources/Logging/fileLogging.swift" ) let observability = ObservabilitySystem.makeForTesting() - XCTAssertThrowsError(try loadModulesGraph( - fileSystem: fs, - manifests: [ - Manifest.createRootManifest( - displayName: "otherPkg", - path: "/otherPkg", - products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), - ProductDescription(name: "LoggingProd", type: .library(.automatic), targets: ["Logging"]), - ], - targets: [ - TargetDescription(name: "Utils", dependencies: ["Logging"]), - TargetDescription(name: "Logging", dependencies: []), - ] - ), - Manifest.createRootManifest( - displayName: "thisPkg", - path: "/thisPkg", - dependencies: [ - .localSourceControl(path: "/otherPkg", requirement: .upToNextMajor(from: "1.0.0")), - ], - targets: [ - TargetDescription( - name: "exe", - dependencies: ["Logging", - .product( - name: "Utils", - package: "otherPkg", - moduleAliases: ["Logging": "UtilsLogging"] - ), - .product( - name: "LoggingProd", - package: "otherPkg", - moduleAliases: ["Logging": "OtherLogging"] - )] - ), - TargetDescription(name: "Logging", dependencies: []), - ] - ), - ], - observabilityScope: observability.topScope - )) { error in + XCTAssertThrowsError( + try loadModulesGraph( + fileSystem: fs, + manifests: [ + Manifest.createRootManifest( + displayName: "otherPkg", + path: "/otherPkg", + products: [ + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "LoggingProd", type: .library(.automatic), targets: ["Logging"]), + ], + targets: [ + TargetDescription(name: "Utils", dependencies: ["Logging"]), + TargetDescription(name: "Logging", dependencies: []), + ] + ), + Manifest.createRootManifest( + displayName: "thisPkg", + path: "/thisPkg", + dependencies: [ + .localSourceControl(path: "/otherPkg", requirement: .upToNextMajor(from: "1.0.0")) + ], + targets: [ + TargetDescription( + name: "exe", + dependencies: [ + "Logging", + .product( + name: "Utils", + package: "otherPkg", + moduleAliases: ["Logging": "UtilsLogging"] + ), + .product( + name: "LoggingProd", + package: "otherPkg", + moduleAliases: ["Logging": "OtherLogging"] + ), + ] + ), + TargetDescription(name: "Logging", dependencies: []), + ] + ), + ], + observabilityScope: observability.topScope + ) + ) { error in var diagnosed = false if let realError = error as? PackageGraphError, - realError - .description == - "multiple aliases: ['UtilsLogging', 'OtherLogging'] found for target 'Logging' in product 'LoggingProd' from package 'otherPkg'" + realError + .description == "multiple aliases: ['UtilsLogging', 'OtherLogging'] found for target 'Logging' in product 'LoggingProd' from package 'otherPkg'" { diagnosed = true } @@ -922,7 +973,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingSameNameTargetsWithAliasesInMultiProducts() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/swift-log/Sources/Logging/fileLogging.swift", "/swift-metrics/Sources/Metrics/file.swift", "/swift-metrics/Sources/Logging/fileLogging.swift" @@ -935,17 +986,17 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "swift-log", path: "/swift-log", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "swift-metrics", path: "/swift-metrics", products: [ - ProductDescription(name: "Metrics", type: .library(.automatic), targets: ["Metrics"]), + ProductDescription(name: "Metrics", type: .library(.automatic), targets: ["Metrics"]) ], targets: [ TargetDescription(name: "Metrics", dependencies: ["Logging"]), @@ -962,30 +1013,34 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "App", - dependencies: [.product( - name: "Logging", - package: "swift-log" - ), - .product( - name: "Metrics", - package: "swift-metrics", - moduleAliases: ["Logging": "MetricsLogging"] - )] - ), + dependencies: [ + .product( + name: "Logging", + package: "swift-log" + ), + .product( + name: "Metrics", + package: "swift-metrics", + moduleAliases: ["Logging": "MetricsLogging"] + ), + ] + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(4) XCTAssertTrue( @@ -1004,7 +1059,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingInvalidSourcesUpstream() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/fooPkg/Sources/Utils/fileUtils.swift", "/fooPkg/Sources/Logging/fileLogging.m", @@ -1018,7 +1073,7 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "fooPkg", path: "/fooPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ TargetDescription(name: "Utils", dependencies: ["Logging"]), @@ -1029,17 +1084,19 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "thisPkg", path: "/thisPkg", dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "exe", - dependencies: ["Logging", - .product( - name: "Utils", - package: "fooPkg", - moduleAliases: ["Logging": "FooLogging"] - )] + dependencies: [ + "Logging", + .product( + name: "Utils", + package: "fooPkg", + moduleAliases: ["Logging": "FooLogging"] + ), + ] ), TargetDescription(name: "Logging", dependencies: []), ] @@ -1059,7 +1116,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingInvalidSourcesNestedUpstream() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/fooPkg/Sources/Utils/fileUtils.swift", "/barPkg/Sources/Logging/fileLogging.m", @@ -1074,43 +1131,45 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "barPkg", path: "/barPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createRootManifest( displayName: "fooPkg", path: "/fooPkg", dependencies: [ - .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ TargetDescription( name: "Utils", dependencies: [.product(name: "Logging", package: "barPkg")] - ), + ) ] ), Manifest.createRootManifest( displayName: "thisPkg", path: "/thisPkg", dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "exe", - dependencies: ["Logging", - .product( - name: "Utils", - package: "fooPkg", - moduleAliases: ["Logging": "FooLogging"] - )] + dependencies: [ + "Logging", + .product( + name: "Utils", + package: "fooPkg", + moduleAliases: ["Logging": "FooLogging"] + ), + ] ), TargetDescription(name: "Logging", dependencies: []), ] @@ -1130,7 +1189,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingInvalidSourcesInNonAliasedModulesUpstream() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/fooPkg/Sources/Utils/fileUtils.swift", "/fooPkg/Sources/Logging/fileLogging.swift", @@ -1139,50 +1198,54 @@ final class ModuleAliasingBuildTests: XCTestCase { "/fooPkg/Sources/Perf/include/filePerf.h" ) let observability = ObservabilitySystem.makeForTesting() - XCTAssertNoThrow(try loadModulesGraph( - fileSystem: fs, - manifests: [ - Manifest.createRootManifest( - displayName: "fooPkg", - path: "/fooPkg", - products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), - ProductDescription(name: "Perf", type: .library(.automatic), targets: ["Perf"]), - ], - targets: [ - TargetDescription(name: "Utils", dependencies: ["Logging"]), - TargetDescription(name: "Logging", dependencies: []), - TargetDescription(name: "Perf", dependencies: []), - ] - ), - Manifest.createRootManifest( - displayName: "thisPkg", - path: "/thisPkg", - dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), - ], - targets: [ - TargetDescription( - name: "exe", - dependencies: ["Logging", - .product( - name: "Utils", - package: "fooPkg", - moduleAliases: ["Logging": "FooLogging"] - )] - ), - TargetDescription(name: "Logging", dependencies: []), - ] - ), - ], - observabilityScope: observability.topScope - )) + XCTAssertNoThrow( + try loadModulesGraph( + fileSystem: fs, + manifests: [ + Manifest.createRootManifest( + displayName: "fooPkg", + path: "/fooPkg", + products: [ + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Perf", type: .library(.automatic), targets: ["Perf"]), + ], + targets: [ + TargetDescription(name: "Utils", dependencies: ["Logging"]), + TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Perf", dependencies: []), + ] + ), + Manifest.createRootManifest( + displayName: "thisPkg", + path: "/thisPkg", + dependencies: [ + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")) + ], + targets: [ + TargetDescription( + name: "exe", + dependencies: [ + "Logging", + .product( + name: "Utils", + package: "fooPkg", + moduleAliases: ["Logging": "FooLogging"] + ), + ] + ), + TargetDescription(name: "Logging", dependencies: []), + ] + ), + ], + observabilityScope: observability.topScope + ) + ) } func testModuleAliasingInvalidSourcesInNonAliasedModulesNestedUpstream() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/fooPkg/Sources/Utils/fileUtils.swift", "/barPkg/Sources/Logging/fileLogging.swift", @@ -1192,65 +1255,69 @@ final class ModuleAliasingBuildTests: XCTestCase { ) let observability = ObservabilitySystem.makeForTesting() - XCTAssertNoThrow(try loadModulesGraph( - fileSystem: fs, - manifests: [ - Manifest.createRootManifest( - displayName: "barPkg", - path: "/barPkg", - products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), - ProductDescription(name: "Perf", type: .library(.automatic), targets: ["Perf"]), - ], - targets: [ - TargetDescription(name: "Logging", dependencies: []), - TargetDescription(name: "Perf", dependencies: []), - ] - ), - Manifest.createRootManifest( - displayName: "fooPkg", - path: "/fooPkg", - dependencies: [ - .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")), - ], - products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), - ], - targets: [ - TargetDescription( - name: "Utils", - dependencies: [.product(name: "Logging", package: "barPkg")] - ), - ] - ), - Manifest.createRootManifest( - displayName: "thisPkg", - path: "/thisPkg", - dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), - ], - targets: [ - TargetDescription( - name: "exe", - dependencies: ["Logging", - .product( - name: "Utils", - package: "fooPkg", - moduleAliases: ["Logging": "FooLogging"] - )] - ), - TargetDescription(name: "Logging", dependencies: []), - ] - ), - ], - observabilityScope: observability.topScope - )) + XCTAssertNoThrow( + try loadModulesGraph( + fileSystem: fs, + manifests: [ + Manifest.createRootManifest( + displayName: "barPkg", + path: "/barPkg", + products: [ + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Perf", type: .library(.automatic), targets: ["Perf"]), + ], + targets: [ + TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Perf", dependencies: []), + ] + ), + Manifest.createRootManifest( + displayName: "fooPkg", + path: "/fooPkg", + dependencies: [ + .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")) + ], + products: [ + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) + ], + targets: [ + TargetDescription( + name: "Utils", + dependencies: [.product(name: "Logging", package: "barPkg")] + ) + ] + ), + Manifest.createRootManifest( + displayName: "thisPkg", + path: "/thisPkg", + dependencies: [ + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")) + ], + targets: [ + TargetDescription( + name: "exe", + dependencies: [ + "Logging", + .product( + name: "Utils", + package: "fooPkg", + moduleAliases: ["Logging": "FooLogging"] + ), + ] + ), + TargetDescription(name: "Logging", dependencies: []), + ] + ), + ], + observabilityScope: observability.topScope + ) + ) } func testModuleAliasingDuplicateTargetNameInNestedUpstream() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file.swift", "/fooPkg/Sources/Utils/fileUtils.swift", "/barPkg/Sources/Logging/fileLogging.swift" @@ -1263,43 +1330,45 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "barPkg", path: "/barPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createRootManifest( displayName: "fooPkg", path: "/fooPkg", dependencies: [ - .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ TargetDescription( name: "Utils", dependencies: [.product(name: "Logging", package: "barPkg")] - ), + ) ] ), Manifest.createRootManifest( displayName: "thisPkg", path: "/thisPkg", dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "exe", - dependencies: ["Logging", - .product( - name: "Utils", - package: "fooPkg", - moduleAliases: ["Logging": "FooLogging"] - )] + dependencies: [ + "Logging", + .product( + name: "Utils", + package: "fooPkg", + moduleAliases: ["Logging": "FooLogging"] + ), + ] ), TargetDescription(name: "Logging", dependencies: []), ] @@ -1309,14 +1378,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(4) @@ -1338,7 +1409,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingOverrideMultipleAliases() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/Logging/file1.swift", "/thisPkg/Sources/Math/file2.swift", "/fooPkg/Sources/Utils/fileUtils.swift", @@ -1366,46 +1437,50 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "fooPkg", path: "/fooPkg", dependencies: [ - .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ TargetDescription( name: "Utils", - dependencies: [.product( - name: "LoggingProd", - package: "barPkg", - moduleAliases: ["Logging": "BarLogging"] - ), - .product( - name: "MathProd", - package: "barPkg", - moduleAliases: ["Math": "BarMath"] - )] - ), + dependencies: [ + .product( + name: "LoggingProd", + package: "barPkg", + moduleAliases: ["Logging": "BarLogging"] + ), + .product( + name: "MathProd", + package: "barPkg", + moduleAliases: ["Math": "BarMath"] + ), + ] + ) ] ), Manifest.createRootManifest( displayName: "thisPkg", path: "/thisPkg", dependencies: [ - .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/fooPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "exe", - dependencies: ["Logging", - "Math", - .product( - name: "Utils", - package: "fooPkg", - moduleAliases: [ - "BarLogging": "FooLogging", - "BarMath": "FooMath", - ] - )] + dependencies: [ + "Logging", + "Math", + .product( + name: "Utils", + package: "fooPkg", + moduleAliases: [ + "BarLogging": "FooLogging", + "BarMath": "FooMath", + ] + ), + ] ), TargetDescription(name: "Logging", dependencies: []), TargetDescription(name: "Math", dependencies: []), @@ -1414,16 +1489,18 @@ final class ModuleAliasingBuildTests: XCTestCase { ], observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) - - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + XCTAssertNoDiagnostics(observability.diagnostics) + + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(6) @@ -1439,8 +1516,9 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "Utils" && $0.module.moduleAliases?["Logging"] == "FooLogging" && $0.module - .moduleAliases?["Math"] == "FooMath" + $0.module.name == "Utils" && $0.module.moduleAliases?["Logging"] == "FooLogging" + && $0.module + .moduleAliases?["Math"] == "FooMath" } ) XCTAssertTrue( @@ -1455,7 +1533,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingAliasSkipUpstreamTargets() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/appPkg/Sources/Foo/file.swift", "/xPkg/Sources/X/file.swift", "/yPkg/Sources/Y/file.swift", @@ -1476,7 +1554,7 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "cPkg", path: "/cPkg", products: [ - ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]), + ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]) ], targets: [ TargetDescription(name: "C", dependencies: ["Foo"]), @@ -1487,10 +1565,10 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "dPkg", path: "/dPkg", products: [ - ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]), + ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]) ], targets: [ - TargetDescription(name: "D", dependencies: []), + TargetDescription(name: "D", dependencies: []) ] ), Manifest.createFileSystemManifest( @@ -1501,7 +1579,7 @@ final class ModuleAliasingBuildTests: XCTestCase { .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")), ], products: [ - ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]), + ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]) ], targets: [ TargetDescription( @@ -1516,33 +1594,35 @@ final class ModuleAliasingBuildTests: XCTestCase { package: "dPkg" ), ] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "aPkg", path: "/aPkg", dependencies: [ - .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]) ], targets: [ TargetDescription( name: "A", - dependencies: [.product( - name: "B", - package: "bPkg" - )] - ), + dependencies: [ + .product( + name: "B", + package: "bPkg" + ) + ] + ) ] ), Manifest.createFileSystemManifest( displayName: "zPkg", path: "/zPkg", products: [ - ProductDescription(name: "Z", type: .library(.automatic), targets: ["Z"]), + ProductDescription(name: "Z", type: .library(.automatic), targets: ["Z"]) ], targets: [ TargetDescription(name: "Z", dependencies: ["Foo"]), @@ -1553,10 +1633,10 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "yPkg", path: "/yPkg", dependencies: [ - .localSourceControl(path: "/zPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/zPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Y", type: .library(.automatic), targets: ["Y"]), + ProductDescription(name: "Y", type: .library(.automatic), targets: ["Y"]) ], targets: [ TargetDescription( @@ -1565,28 +1645,30 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "Z", package: "zPkg" - ), + ) ] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "xPkg", path: "/xPkg", dependencies: [ - .localSourceControl(path: "/yPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/yPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]) ], targets: [ TargetDescription( name: "X", - dependencies: [.product( - name: "Y", - package: "yPkg" - )] - ), + dependencies: [ + .product( + name: "Y", + package: "yPkg" + ) + ] + ) ] ), Manifest.createRootManifest( @@ -1599,17 +1681,19 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "App", - dependencies: ["Foo", - .product( - name: "A", - package: "aPkg", - moduleAliases: ["Foo": "FooA"] - ), - .product( - name: "X", - package: "xPkg", - moduleAliases: ["Foo": "FooX"] - )] + dependencies: [ + "Foo", + .product( + name: "A", + package: "aPkg", + moduleAliases: ["Foo": "FooA"] + ), + .product( + name: "X", + package: "xPkg", + moduleAliases: ["Foo": "FooX"] + ), + ] ), TargetDescription(name: "Foo", dependencies: []), ] @@ -1619,14 +1703,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(11) @@ -1670,7 +1756,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingAllConflictingAliasesFromMultiProducts() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/aPkg/Sources/A/main.swift", + "/aPkg/Sources/A/main.swift", "/aPkg/Sources/A/file.swift", "/bPkg/Sources/B/file.swift", "/bPkg/Sources/Utils/file.swift", @@ -1690,26 +1776,28 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "gPkg", path: "/gPkg", dependencies: [ - .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "G", type: .library(.automatic), targets: ["G"]), + ProductDescription(name: "G", type: .library(.automatic), targets: ["G"]) ], targets: [ TargetDescription( name: "G", - dependencies: [.product( - name: "D", - package: "dPkg" - )] - ), + dependencies: [ + .product( + name: "D", + package: "dPkg" + ) + ] + ) ] ), Manifest.createFileSystemManifest( displayName: "dPkg", path: "/dPkg", products: [ - ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]), + ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]) ], targets: [ TargetDescription(name: "D", dependencies: ["Utils", "Log"]), @@ -1721,7 +1809,7 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "cPkg", path: "/cPkg", dependencies: [ - .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]), @@ -1736,7 +1824,7 @@ final class ModuleAliasingBuildTests: XCTestCase { name: "D", package: "dPkg", moduleAliases: ["Log": "ZLog"] - ), + ) ] ), ] @@ -1745,10 +1833,10 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "bPkg", path: "/bPkg", dependencies: [ - .localSourceControl(path: "/cPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/cPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]), + ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]) ], targets: [ TargetDescription( @@ -1758,8 +1846,10 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "C", package: "cPkg", - moduleAliases: ["Utils": "YUtils", - "Log": "YLog"] + moduleAliases: [ + "Utils": "YUtils", + "Log": "YLog", + ] ), ] ), @@ -1784,11 +1874,13 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "B", package: "bPkg", - moduleAliases: ["Utils": "XUtils", - "YLog": "XLog"] + moduleAliases: [ + "Utils": "XUtils", + "YLog": "XLog", + ] ), ] - ), + ) ] ), ], @@ -1796,14 +1888,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(9) @@ -1814,59 +1908,72 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "B" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "B" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "XUtils" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases? - .count == 1 + $0.module.name == "XUtils" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases? + .count == 1 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "C" && $0.module.moduleAliases?["Log"] == "XLog" && $0.module - .moduleAliases?["Utils"] == "YUtils" && $0.module.moduleAliases?.count == 2 + $0.module.name == "C" && $0.module.moduleAliases?["Log"] == "XLog" + && $0.module + .moduleAliases?["Utils"] == "YUtils" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "XLog" && $0.module.moduleAliases?["Log"] == "XLog" && $0.module - .moduleAliases?["Utils"] == "YUtils" && $0.module.moduleAliases?.count == 2 + $0.module.name == "XLog" && $0.module.moduleAliases?["Log"] == "XLog" + && $0.module + .moduleAliases?["Utils"] == "YUtils" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "D" && $0.module.moduleAliases?["Utils"] == "YUtils" && $0.module - .moduleAliases?["Log"] == "ZLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "D" && $0.module.moduleAliases?["Utils"] == "YUtils" + && $0.module + .moduleAliases?["Log"] == "ZLog" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "YUtils" && $0.module.moduleAliases?["Utils"] == "YUtils" && $0.module - .moduleAliases? - .count == 1 + $0.module.name == "YUtils" && $0.module.moduleAliases?["Utils"] == "YUtils" + && $0.module + .moduleAliases? + .count == 1 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "ZLog" && $0.module.moduleAliases?["Log"] == "ZLog" && $0.module.moduleAliases? - .count == 1 + $0.module.name == "ZLog" && $0.module.moduleAliases?["Log"] == "ZLog" + && $0.module.moduleAliases? + .count == 1 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "G" && $0.module.moduleAliases?["Utils"] == "YUtils" && $0.module - .moduleAliases?["Log"] == "ZLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "G" && $0.module.moduleAliases?["Utils"] == "YUtils" + && $0.module + .moduleAliases?["Log"] == "ZLog" + && $0.module.moduleAliases?.count == 2 } ) } @@ -1874,7 +1981,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingSomeConflictingAliasesInMultiProducts() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/aPkg/Sources/A/main.swift", + "/aPkg/Sources/A/main.swift", "/aPkg/Sources/A/file.swift", "/bPkg/Sources/B/file.swift", "/cPkg/Sources/C/file.swift", @@ -1892,42 +1999,43 @@ final class ModuleAliasingBuildTests: XCTestCase { Manifest.createFileSystemManifest( displayName: "hPkg", path: "/hPkg", - dependencies: [ - ], + dependencies: [], products: [ - ProductDescription(name: "H", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "H", type: .library(.automatic), targets: ["Utils"]) ], targets: [ TargetDescription( name: "Utils", dependencies: [] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "gPkg", path: "/gPkg", dependencies: [ - .localSourceControl(path: "/hPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/hPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "G", type: .library(.automatic), targets: ["G"]), + ProductDescription(name: "G", type: .library(.automatic), targets: ["G"]) ], targets: [ TargetDescription( name: "G", - dependencies: [.product( - name: "H", - package: "hPkg" - )] - ), + dependencies: [ + .product( + name: "H", + package: "hPkg" + ) + ] + ) ] ), Manifest.createFileSystemManifest( displayName: "dPkg", path: "/dPkg", products: [ - ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]), + ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]) ], targets: [ TargetDescription(name: "D", dependencies: ["Utils", "Log"]), @@ -1939,10 +2047,10 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "cPkg", path: "/cPkg", dependencies: [ - .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]), + ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]) ], targets: [ TargetDescription( @@ -1952,19 +2060,19 @@ final class ModuleAliasingBuildTests: XCTestCase { name: "D", package: "dPkg", moduleAliases: ["Log": "ZLog"] - ), + ) ] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "bPkg", path: "/bPkg", dependencies: [ - .localSourceControl(path: "/cPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/cPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]), + ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]) ], targets: [ TargetDescription( @@ -1973,11 +2081,13 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "C", package: "cPkg", - moduleAliases: ["Utils": "YUtils", - "ZLog": "YLog"] - ), + moduleAliases: [ + "Utils": "YUtils", + "ZLog": "YLog", + ] + ) ] - ), + ) ] ), Manifest.createRootManifest( @@ -1994,8 +2104,10 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "B", package: "bPkg", - moduleAliases: ["YUtils": "XUtils", - "YLog": "XLog"] + moduleAliases: [ + "YUtils": "XUtils", + "YLog": "XLog", + ] ), .product( name: "G", @@ -2003,7 +2115,7 @@ final class ModuleAliasingBuildTests: XCTestCase { moduleAliases: ["Utils": "GUtils"] ), ] - ), + ) ] ), ], @@ -2011,14 +2123,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(8) @@ -2026,59 +2140,70 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "A" && $0.module.moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases? - .count == 1 + $0.module.name == "A" && $0.module.moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases? + .count == 1 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "B" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "B" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "C" && $0.module.moduleAliases?["Log"] == "XLog" && $0.module - .moduleAliases?["Utils"] == "XUtils" && $0.module.moduleAliases?.count == 2 + $0.module.name == "C" && $0.module.moduleAliases?["Log"] == "XLog" + && $0.module + .moduleAliases?["Utils"] == "XUtils" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "D" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "D" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "XUtils" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases? - .count == 1 + $0.module.name == "XUtils" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases? + .count == 1 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "XLog" && $0.module.moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases? - .count == 1 + $0.module.name == "XLog" && $0.module.moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases? + .count == 1 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "G" && $0.module.moduleAliases?["Utils"] == "GUtils" && $0.module.moduleAliases? - .count == 1 + $0.module.name == "G" && $0.module.moduleAliases?["Utils"] == "GUtils" + && $0.module.moduleAliases? + .count == 1 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "GUtils" && $0.module.moduleAliases?["Utils"] == "GUtils" && $0.module - .moduleAliases? - .count == 1 + $0.module.name == "GUtils" && $0.module.moduleAliases?["Utils"] == "GUtils" + && $0.module + .moduleAliases? + .count == 1 } ) } @@ -2086,7 +2211,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingMergeAliasesOfSameTargets() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/aPkg/Sources/A/main.swift", + "/aPkg/Sources/A/main.swift", "/aPkg/Sources/A/file.swift", "/bPkg/Sources/B/file.swift", "/cPkg/Sources/C/file.swift", @@ -2105,49 +2230,53 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "hPkg", path: "/hPkg", dependencies: [ - .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "H", type: .library(.automatic), targets: ["H"]), + ProductDescription(name: "H", type: .library(.automatic), targets: ["H"]) ], targets: [ TargetDescription( name: "H", - dependencies: [.product( - name: "D", - package: "dPkg" - )] - ), + dependencies: [ + .product( + name: "D", + package: "dPkg" + ) + ] + ) ] ), Manifest.createFileSystemManifest( displayName: "gPkg", path: "/gPkg", dependencies: [ - .localSourceControl(path: "/hPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/hPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "G", type: .library(.automatic), targets: ["G"]), + ProductDescription(name: "G", type: .library(.automatic), targets: ["G"]) ], targets: [ TargetDescription( name: "G", - dependencies: [.product( - name: "H", - package: "hPkg", - moduleAliases: [ - "Utils": "GUtils", - "Log": "GLog", - ] - )] - ), + dependencies: [ + .product( + name: "H", + package: "hPkg", + moduleAliases: [ + "Utils": "GUtils", + "Log": "GLog", + ] + ) + ] + ) ] ), Manifest.createFileSystemManifest( displayName: "dPkg", path: "/dPkg", products: [ - ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]), + ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]) ], targets: [ TargetDescription(name: "D", dependencies: ["Utils", "Log"]), @@ -2159,10 +2288,10 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "cPkg", path: "/cPkg", dependencies: [ - .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/dPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]), + ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]) ], targets: [ TargetDescription( @@ -2172,19 +2301,19 @@ final class ModuleAliasingBuildTests: XCTestCase { name: "D", package: "dPkg", moduleAliases: ["Log": "ZLog"] - ), + ) ] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "bPkg", path: "/bPkg", dependencies: [ - .localSourceControl(path: "/cPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/cPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]), + ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]) ], targets: [ TargetDescription( @@ -2193,11 +2322,13 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "C", package: "cPkg", - moduleAliases: ["Utils": "YUtils", - "ZLog": "YLog"] - ), + moduleAliases: [ + "Utils": "YUtils", + "ZLog": "YLog", + ] + ) ] - ), + ) ] ), Manifest.createRootManifest( @@ -2218,11 +2349,13 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "B", package: "bPkg", - moduleAliases: ["YUtils": "XUtils", - "YLog": "XLog"] + moduleAliases: [ + "YUtils": "XUtils", + "YLog": "XLog", + ] ), ] - ), + ) ] ), ], @@ -2230,72 +2363,88 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(8) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "A" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "A" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "B" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "B" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "C" && $0.module.moduleAliases?["Log"] == "XLog" && $0.module - .moduleAliases?["Utils"] == "XUtils" && $0.module.moduleAliases?.count == 2 + $0.module.name == "C" && $0.module.moduleAliases?["Log"] == "XLog" + && $0.module + .moduleAliases?["Utils"] == "XUtils" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "D" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "D" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "XUtils" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases? - .count == 1 + $0.module.name == "XUtils" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases? + .count == 1 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "XLog" && $0.module.moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases? - .count == 1 + $0.module.name == "XLog" && $0.module.moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases? + .count == 1 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "G" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "G" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases?.count == 2 } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "H" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases?["Log"] == "XLog" && $0.module.moduleAliases?.count == 2 + $0.module.name == "H" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases?["Log"] == "XLog" + && $0.module.moduleAliases?.count == 2 } ) } @@ -2303,7 +2452,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingOverrideSameNameTargetAndDepWithAliases() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/appPkg/Sources/Utils/file1.swift", "/appPkg/Sources/Render/file2.swift", "/libPkg/Sources/Lib/fileLib.swift", @@ -2321,17 +2470,17 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "drawPkg", path: "/drawPkg", products: [ - ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]), + ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]) ], targets: [ - TargetDescription(name: "Render", dependencies: []), + TargetDescription(name: "Render", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "gamePkg", path: "/gamePkg", dependencies: [ - .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ ProductDescription(name: "Game", type: .library(.automatic), targets: ["Game"]), @@ -2348,7 +2497,7 @@ final class ModuleAliasingBuildTests: XCTestCase { name: "DrawProd", package: "drawPkg", moduleAliases: ["Render": "DrawRender"] - ), + ) ] ), ] @@ -2357,10 +2506,10 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "libPkg", path: "/libPkg", dependencies: [ - .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]), + ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]) ], targets: [ TargetDescription( @@ -2377,28 +2526,30 @@ final class ModuleAliasingBuildTests: XCTestCase { moduleAliases: ["Render": "GameRender"] ), ] - ), + ) ] ), Manifest.createRootManifest( displayName: "appPkg", path: "/appPkg", dependencies: [ - .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "App", - dependencies: ["Utils", - "Render", - .product( - name: "LibProd", - package: "libPkg", - moduleAliases: [ - "GameUtils": "LibUtils", - "GameRender": "LibRender", - ] - )] + dependencies: [ + "Utils", + "Render", + .product( + name: "LibProd", + package: "libPkg", + moduleAliases: [ + "GameUtils": "LibUtils", + "GameRender": "LibRender", + ] + ), + ] ), TargetDescription(name: "Utils", dependencies: []), TargetDescription(name: "Render", dependencies: []), @@ -2409,14 +2560,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(8) @@ -2424,8 +2577,9 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "LibUtils" && $0.module - .moduleAliases?["Render"] == "LibRender" + $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "LibUtils" + && $0.module + .moduleAliases?["Render"] == "LibRender" } ) XCTAssertTrue( @@ -2439,8 +2593,9 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "Game" && $0.module.moduleAliases?["Utils"] == "LibUtils" && $0.module - .moduleAliases?["Render"] == nil + $0.module.name == "Game" && $0.module.moduleAliases?["Utils"] == "LibUtils" + && $0.module + .moduleAliases?["Render"] == nil } ) XCTAssertTrue( @@ -2456,7 +2611,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingAddOverrideAliasesUpstream() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/appPkg/Sources/Utils/file1.swift", "/appPkg/Sources/Render/file2.swift", "/libPkg/Sources/Lib/fileLib.swift", @@ -2473,17 +2628,17 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "drawPkg", path: "/drawPkg", products: [ - ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]), + ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]) ], targets: [ - TargetDescription(name: "Render", dependencies: []), + TargetDescription(name: "Render", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "gamePkg", path: "/gamePkg", dependencies: [ - .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ ProductDescription(name: "Game", type: .library(.automatic), targets: ["Utils"]), @@ -2500,7 +2655,7 @@ final class ModuleAliasingBuildTests: XCTestCase { name: "DrawProd", package: "drawPkg", moduleAliases: ["Render": "DrawRender"] - ), + ) ] ), ] @@ -2509,42 +2664,46 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "libPkg", path: "/libPkg", dependencies: [ - .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]), + ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]) ], targets: [ TargetDescription( name: "Lib", - dependencies: [.product( - name: "UtilsProd", - package: "gamePkg", - moduleAliases: ["Utils": "GameUtils"] - ), - .product( - name: "RenderProd", - package: "gamePkg", - moduleAliases: ["Render": "GameRender"] - )] - ), + dependencies: [ + .product( + name: "UtilsProd", + package: "gamePkg", + moduleAliases: ["Utils": "GameUtils"] + ), + .product( + name: "RenderProd", + package: "gamePkg", + moduleAliases: ["Render": "GameRender"] + ), + ] + ) ] ), Manifest.createRootManifest( displayName: "appPkg", path: "/appPkg", dependencies: [ - .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "App", - dependencies: ["Utils", - "Render", - .product( - name: "LibProd", - package: "libPkg" - )] + dependencies: [ + "Utils", + "Render", + .product( + name: "LibProd", + package: "libPkg" + ), + ] ), TargetDescription(name: "Utils", dependencies: []), TargetDescription(name: "Render", dependencies: []), @@ -2555,14 +2714,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(7) @@ -2570,8 +2731,9 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "GameUtils" && $0.module - .moduleAliases?["Render"] == "GameRender" + $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "GameUtils" + && $0.module + .moduleAliases?["Render"] == "GameRender" } ) XCTAssertTrue( @@ -2594,7 +2756,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingOverrideUpstreamTargetsWithAliases() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/appPkg/Sources/Utils/file1.swift", "/appPkg/Sources/Render/file2.swift", "/libPkg/Sources/Lib/fileLib.swift", @@ -2612,17 +2774,17 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "drawPkg", path: "/drawPkg", products: [ - ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]), + ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]) ], targets: [ - TargetDescription(name: "Render", dependencies: []), + TargetDescription(name: "Render", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "gamePkg", path: "/gamePkg", dependencies: [ - .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ ProductDescription(name: "Game", type: .library(.automatic), targets: ["Utils"]), @@ -2641,7 +2803,7 @@ final class ModuleAliasingBuildTests: XCTestCase { name: "DrawProd", package: "drawPkg", moduleAliases: ["Render": "DrawRender"] - ), + ) ] ), ] @@ -2650,46 +2812,50 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "libPkg", path: "/libPkg", dependencies: [ - .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]), + ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]) ], targets: [ TargetDescription( name: "Lib", - dependencies: [.product( - name: "UtilsProd", - package: "gamePkg", - moduleAliases: ["Utils": "GameUtils"] - ), - .product( - name: "RenderProd", - package: "gamePkg", - moduleAliases: ["Render": "GameRender"] - ), - .product( - name: "SceneProd", - package: "gamePkg" - )] - ), + dependencies: [ + .product( + name: "UtilsProd", + package: "gamePkg", + moduleAliases: ["Utils": "GameUtils"] + ), + .product( + name: "RenderProd", + package: "gamePkg", + moduleAliases: ["Render": "GameRender"] + ), + .product( + name: "SceneProd", + package: "gamePkg" + ), + ] + ) ] ), Manifest.createRootManifest( displayName: "appPkg", path: "/appPkg", dependencies: [ - .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "App", - dependencies: ["Utils", - "Render", - .product( - name: "LibProd", - package: "libPkg" - )] + dependencies: [ + "Utils", + "Render", + .product( + name: "LibProd", + package: "libPkg" + ), + ] ), TargetDescription(name: "Utils", dependencies: []), TargetDescription(name: "Render", dependencies: []), @@ -2700,14 +2866,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(8) @@ -2715,8 +2883,9 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "GameUtils" && $0.module - .moduleAliases?["Render"] == "GameRender" + $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "GameUtils" + && $0.module + .moduleAliases?["Render"] == "GameRender" } ) XCTAssertTrue( @@ -2743,7 +2912,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingOverrideUpstreamTargetsWithAliasesMultipleAliasesInProduct() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/appPkg/Sources/Utils/file1.swift", "/appPkg/Sources/Render/file2.swift", "/libPkg/Sources/Lib/fileLib.swift", @@ -2760,17 +2929,17 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "drawPkg", path: "/drawPkg", products: [ - ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]), + ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]) ], targets: [ - TargetDescription(name: "Render", dependencies: []), + TargetDescription(name: "Render", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "gamePkg", path: "/gamePkg", dependencies: [ - .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ ProductDescription(name: "GameProd", type: .library(.automatic), targets: ["Game"]), @@ -2795,7 +2964,7 @@ final class ModuleAliasingBuildTests: XCTestCase { name: "DrawProd", package: "drawPkg", moduleAliases: ["Render": "DrawRender"] - ), + ) ] ), ] @@ -2804,44 +2973,48 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "libPkg", path: "/libPkg", dependencies: [ - .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]), + ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]) ], targets: [ TargetDescription( name: "Lib", - dependencies: [.product( - name: "UtilsProd", - package: "gamePkg", - moduleAliases: [ - "Utils": "GameUtils", - "Render": "GameRender", - ] - )] - ), + dependencies: [ + .product( + name: "UtilsProd", + package: "gamePkg", + moduleAliases: [ + "Utils": "GameUtils", + "Render": "GameRender", + ] + ) + ] + ) ] ), Manifest.createRootManifest( displayName: "appPkg", path: "/appPkg", dependencies: [ - .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "App", - dependencies: ["Utils", - "Render", - .product( - name: "LibProd", - package: "libPkg", - moduleAliases: [ - "GameUtils": "LibUtils", - "GameRender": "LibRender", - ] - )] + dependencies: [ + "Utils", + "Render", + .product( + name: "LibProd", + package: "libPkg", + moduleAliases: [ + "GameUtils": "LibUtils", + "GameRender": "LibRender", + ] + ), + ] ), TargetDescription(name: "Utils", dependencies: []), TargetDescription(name: "Render", dependencies: []), @@ -2852,14 +3025,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(7) @@ -2867,8 +3042,9 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "LibUtils" && $0.module - .moduleAliases?["Render"] == "LibRender" + $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "LibUtils" + && $0.module + .moduleAliases?["Render"] == "LibRender" } ) XCTAssertTrue( @@ -2895,7 +3071,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingOverrideUpstreamTargetsWithAliasesDownstream() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/appPkg/Sources/Utils/file1.swift", "/appPkg/Sources/Render/file2.swift", "/libPkg/Sources/Lib/fileLib.swift", @@ -2914,17 +3090,17 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "drawPkg", path: "/drawPkg", products: [ - ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]), + ProductDescription(name: "DrawProd", type: .library(.automatic), targets: ["Render"]) ], targets: [ - TargetDescription(name: "Render", dependencies: []), + TargetDescription(name: "Render", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "gamePkg", path: "/gamePkg", dependencies: [ - .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/drawPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ ProductDescription(name: "Game", type: .library(.automatic), targets: ["Game"]), @@ -2943,7 +3119,7 @@ final class ModuleAliasingBuildTests: XCTestCase { name: "DrawProd", package: "drawPkg", moduleAliases: ["Render": "DrawRender"] - ), + ) ] ), ] @@ -2952,50 +3128,54 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "libPkg", path: "/libPkg", dependencies: [ - .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/gamePkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]), + ProductDescription(name: "LibProd", type: .library(.automatic), targets: ["Lib"]) ], targets: [ TargetDescription( name: "Lib", - dependencies: [.product( - name: "UtilsProd", - package: "gamePkg", - moduleAliases: ["Utils": "GameUtils"] - ), - .product( - name: "RenderProd", - package: "gamePkg", - moduleAliases: ["Render": "GameRender"] - ), - .product( - name: "SceneProd", - package: "gamePkg" - )] - ), + dependencies: [ + .product( + name: "UtilsProd", + package: "gamePkg", + moduleAliases: ["Utils": "GameUtils"] + ), + .product( + name: "RenderProd", + package: "gamePkg", + moduleAliases: ["Render": "GameRender"] + ), + .product( + name: "SceneProd", + package: "gamePkg" + ), + ] + ) ] ), Manifest.createRootManifest( displayName: "appPkg", path: "/appPkg", dependencies: [ - .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/libPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "App", - dependencies: ["Utils", - "Render", - .product( - name: "LibProd", - package: "libPkg", - moduleAliases: [ - "GameUtils": "LibUtils", - "GameRender": "LibRender", - ] - )] + dependencies: [ + "Utils", + "Render", + .product( + name: "LibProd", + package: "libPkg", + moduleAliases: [ + "GameUtils": "LibUtils", + "GameRender": "LibRender", + ] + ), + ] ), TargetDescription(name: "Utils", dependencies: []), TargetDescription(name: "Render", dependencies: []), @@ -3006,14 +3186,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(9) @@ -3021,8 +3203,9 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "LibUtils" && $0.module - .moduleAliases?["Render"] == "LibRender" + $0.module.name == "Lib" && $0.module.moduleAliases?["Utils"] == "LibUtils" + && $0.module + .moduleAliases?["Render"] == "LibRender" } ) XCTAssertTrue( @@ -3053,7 +3236,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingSameTargetFromUpstreamWithoutAlias() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/MyLogging/file.swift", "/fooPkg/Sources/Utils/fileUtils.swift", "/barPkg/Sources/Logging/fileLogging.swift" @@ -3067,29 +3250,31 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "barPkg", path: "/barPkg", products: [ - ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "Logging", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "fooPkg", path: "/fooPkg", dependencies: [ - .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ TargetDescription( name: "Utils", - dependencies: [.product( - name: "Logging", - package: "barPkg" - )] - ), + dependencies: [ + .product( + name: "Logging", + package: "barPkg" + ) + ] + ) ] ), Manifest.createRootManifest( @@ -3102,16 +3287,18 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "exe", - dependencies: ["MyLogging", - .product( - name: "Utils", - package: "fooPkg", - moduleAliases: ["Logging": "FooLogging"] - ), - .product( - name: "Logging", - package: "barPkg" - )] + dependencies: [ + "MyLogging", + .product( + name: "Utils", + package: "fooPkg", + moduleAliases: ["Logging": "FooLogging"] + ), + .product( + name: "Logging", + package: "barPkg" + ), + ] ), TargetDescription(name: "MyLogging", dependencies: []), ] @@ -3121,14 +3308,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(4) @@ -3154,7 +3343,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingDuplicateTargetNamesFromMultiplePkgs() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/thisPkg/Sources/exe/main.swift", + "/thisPkg/Sources/exe/main.swift", "/thisPkg/Sources/MyLogging/file.swift", "/fooPkg/Sources/Utils/fileUtils.swift", "/barPkg/Sources/Logging/fileLogging.swift", @@ -3169,39 +3358,41 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "carPkg", path: "/carPkg", products: [ - ProductDescription(name: "CarLog", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "CarLog", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "barPkg", path: "/barPkg", products: [ - ProductDescription(name: "BarLog", type: .library(.automatic), targets: ["Logging"]), + ProductDescription(name: "BarLog", type: .library(.automatic), targets: ["Logging"]) ], targets: [ - TargetDescription(name: "Logging", dependencies: []), + TargetDescription(name: "Logging", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "fooPkg", path: "/fooPkg", dependencies: [ - .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "UtilsProd", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "UtilsProd", type: .library(.automatic), targets: ["Utils"]) ], targets: [ TargetDescription( name: "Utils", - dependencies: [.product( - name: "BarLog", - package: "barPkg" - )] - ), + dependencies: [ + .product( + name: "BarLog", + package: "barPkg" + ) + ] + ) ] ), Manifest.createRootManifest( @@ -3214,17 +3405,19 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "exe", - dependencies: ["MyLogging", - .product( - name: "UtilsProd", - package: "fooPkg", - moduleAliases: ["Logging": "FooLogging"] - ), - .product( - name: "CarLog", - package: "carPkg", - moduleAliases: ["Logging": "CarLogging"] - )] + dependencies: [ + "MyLogging", + .product( + name: "UtilsProd", + package: "fooPkg", + moduleAliases: ["Logging": "FooLogging"] + ), + .product( + name: "CarLog", + package: "carPkg", + moduleAliases: ["Logging": "CarLogging"] + ), + ] ), TargetDescription(name: "MyLogging", dependencies: []), ] @@ -3234,14 +3427,16 @@ final class ModuleAliasingBuildTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(5) @@ -3271,7 +3466,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingTargetAndProductTargetWithSameName() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/appPkg/Sources/Utils/file.swift", "/xPkg/Sources/X/file.swift", "/xPkg/Sources/Utils/file.swift" @@ -3284,7 +3479,7 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "xpkg", path: "/xPkg", products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]) ], targets: [ TargetDescription(name: "X", dependencies: ["Utils"]), @@ -3295,17 +3490,19 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "appPkg", path: "/appPkg", dependencies: [ - .localSourceControl(path: "/xPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/xPkg", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription( name: "App", - dependencies: ["Utils", - .product( - name: "X", - package: "xpkg", - moduleAliases: ["Utils": "XUtils"] - )] + dependencies: [ + "Utils", + .product( + name: "X", + package: "xpkg", + moduleAliases: ["Utils": "XUtils"] + ), + ] ), TargetDescription(name: "Utils", dependencies: []), ] @@ -3314,14 +3511,16 @@ final class ModuleAliasingBuildTests: XCTestCase { observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(4) XCTAssertTrue( @@ -3339,7 +3538,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingProductTargetsWithSameName1() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/xPkg/Sources/X/file.swift", "/yPkg/Sources/Utils/file.swift", "/aPkg/Sources/A/file.swift", @@ -3354,20 +3553,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "cpkg", path: "/cPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( displayName: "bpkg", path: "/bPkg", dependencies: [ - .localSourceControl(path: "/cPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/cPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]), + ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]) ], targets: [ TargetDescription( @@ -3376,19 +3575,19 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "Utils", package: "cpkg" - ), + ) ] - ), + ) ] ), Manifest.createRootManifest( displayName: "apkg", path: "/aPkg", dependencies: [ - .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]) ], targets: [ TargetDescription( @@ -3397,29 +3596,29 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "B", package: "bpkg" - ), + ) ] - ), + ) ] ), Manifest.createRootManifest( displayName: "ypkg", path: "/yPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( displayName: "xpkg", path: "/xPkg", dependencies: [ - .localSourceControl(path: "/yPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/yPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]) ], targets: [ TargetDescription( @@ -3428,9 +3627,9 @@ final class ModuleAliasingBuildTests: XCTestCase { .product( name: "Utils", package: "ypkg" - ), + ) ] - ), + ) ] ), Manifest.createRootManifest( @@ -3455,21 +3654,23 @@ final class ModuleAliasingBuildTests: XCTestCase { moduleAliases: ["Utils": "AUtils"] ), ] - ), + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(6) XCTAssertTrue( @@ -3499,7 +3700,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingUpstreamProductTargetsWithSameName2() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/aPkg/Sources/A/file.swift", "/bPkg/Sources/Utils/file.swift", "/cPkg/Sources/Utils/file.swift", @@ -3515,20 +3716,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "zpkg", path: "/zPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( displayName: "ypkg", path: "/yPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( @@ -3540,7 +3741,7 @@ final class ModuleAliasingBuildTests: XCTestCase { .localSourceControl(path: "/zPkg", requirement: .upToNextMajor(from: "1.0.0")), ], products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]) ], targets: [ TargetDescription( @@ -3556,27 +3757,27 @@ final class ModuleAliasingBuildTests: XCTestCase { moduleAliases: ["Utils": "YUtils"] ), ] - ), + ) ] ), Manifest.createRootManifest( displayName: "cpkg", path: "/cPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( displayName: "bpkg", path: "/bPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( @@ -3588,7 +3789,7 @@ final class ModuleAliasingBuildTests: XCTestCase { .localSourceControl(path: "/cPkg", requirement: .upToNextMajor(from: "1.0.0")), ], products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]) ], targets: [ TargetDescription( @@ -3604,7 +3805,7 @@ final class ModuleAliasingBuildTests: XCTestCase { moduleAliases: ["Utils": "BUtils"] ), ] - ), + ) ] ), Manifest.createRootManifest( @@ -3631,21 +3832,23 @@ final class ModuleAliasingBuildTests: XCTestCase { ), ], type: .executable - ), + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(7) XCTAssertTrue(result.targetMap.values.contains { $0.module.name == "X" && $0.module.moduleAliases == nil }) @@ -3673,7 +3876,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingUpstreamProductTargetsWithSameName3() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/aPkg/Sources/A/file.swift", "/aPkg/Sources/Utils/file.swift", "/xPkg/Sources/X/file.swift", @@ -3688,20 +3891,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "zpkg", path: "/zPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( displayName: "ypkg", path: "/yPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( @@ -3713,7 +3916,7 @@ final class ModuleAliasingBuildTests: XCTestCase { .localSourceControl(path: "/zPkg", requirement: .upToNextMajor(from: "1.0.0")), ], products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]) ], targets: [ TargetDescription( @@ -3729,14 +3932,14 @@ final class ModuleAliasingBuildTests: XCTestCase { moduleAliases: ["Utils": "YUtils"] ), ] - ), + ) ] ), Manifest.createRootManifest( displayName: "apkg", path: "/aPkg", products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]) ], targets: [ TargetDescription(name: "A", dependencies: ["Utils"]), @@ -3766,21 +3969,23 @@ final class ModuleAliasingBuildTests: XCTestCase { ), ], type: .executable - ), + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(6) XCTAssertTrue(result.targetMap.values.contains { $0.module.name == "X" && $0.module.moduleAliases == nil }) @@ -3803,7 +4008,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingUpstreamProductTargetsWithSameName4() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/aPkg/Sources/A/file.swift", "/aPkg/Sources/Utils/file.swift", "/xPkg/Sources/X/file.swift", @@ -3818,20 +4023,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "zpkg", path: "/zPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( displayName: "ypkg", path: "/yPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( @@ -3843,7 +4048,7 @@ final class ModuleAliasingBuildTests: XCTestCase { .localSourceControl(path: "/zPkg", requirement: .upToNextMajor(from: "1.0.0")), ], products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]) ], targets: [ TargetDescription( @@ -3859,17 +4064,17 @@ final class ModuleAliasingBuildTests: XCTestCase { moduleAliases: ["Utils": "YUtils"] ), ] - ), + ) ] ), Manifest.createRootManifest( displayName: "apkg", path: "/aPkg", products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createRootManifest( @@ -3896,21 +4101,23 @@ final class ModuleAliasingBuildTests: XCTestCase { ), ], type: .executable - ), + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(5) XCTAssertTrue(result.targetMap.values.contains { $0.module.name == "X" && $0.module.moduleAliases == nil }) @@ -3933,7 +4140,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingChainedAliases1() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/aPkg/Sources/A/file.swift", "/aPkg/Sources/Utils/file.swift", "/bPkg/Sources/Utils/file.swift", @@ -3949,20 +4156,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "ypkg", path: "/yPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "xpkg", path: "/xPkg", dependencies: [ - .localSourceControl(path: "/yPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/yPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]) ], targets: [ TargetDescription( @@ -3983,20 +4190,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "bpkg", path: "/bPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "apkg", path: "/aPkg", dependencies: [ - .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]) ], targets: [ TargetDescription( @@ -4023,51 +4230,57 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "App", - dependencies: [.product( - name: "A", - package: "apkg", - moduleAliases: [ - "Utils": "AUtils", - "FooUtils": "AFooUtils", - ] - ), - .product( - name: "X", - package: "xpkg", - moduleAliases: [ - "Utils": "XUtils", - "FooUtils": "XFooUtils", - ] - )] - ), + dependencies: [ + .product( + name: "A", + package: "apkg", + moduleAliases: [ + "Utils": "AUtils", + "FooUtils": "AFooUtils", + ] + ), + .product( + name: "X", + package: "xpkg", + moduleAliases: [ + "Utils": "XUtils", + "FooUtils": "XFooUtils", + ] + ), + ] + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(7) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "A" && $0.module.moduleAliases?["Utils"] == "AUtils" && $0.module - .moduleAliases?["FooUtils"] == "AFooUtils" + $0.module.name == "A" && $0.module.moduleAliases?["Utils"] == "AUtils" + && $0.module + .moduleAliases?["FooUtils"] == "AFooUtils" } ) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "X" && $0.module.moduleAliases?["Utils"] == "XUtils" && $0.module - .moduleAliases?["FooUtils"] == "XFooUtils" + $0.module.name == "X" && $0.module.moduleAliases?["Utils"] == "XUtils" + && $0.module + .moduleAliases?["FooUtils"] == "XFooUtils" } ) XCTAssertTrue( @@ -4092,7 +4305,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingChainedAliases2() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/aPkg/Sources/A/file.swift", "/aPkg/Sources/Utils/file.swift", "/bPkg/Sources/Utils/file.swift", @@ -4109,20 +4322,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "zpkg", path: "/zPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "ypkg", path: "/yPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( @@ -4134,7 +4347,7 @@ final class ModuleAliasingBuildTests: XCTestCase { .localSourceControl(path: "/zPkg", requirement: .upToNextMajor(from: "1.0.0")), ], products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]) ], targets: [ TargetDescription( @@ -4150,17 +4363,17 @@ final class ModuleAliasingBuildTests: XCTestCase { package: "zpkg" ), ] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "bpkg", path: "/bPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( @@ -4168,10 +4381,10 @@ final class ModuleAliasingBuildTests: XCTestCase { path: "/aPkg", toolsVersion: .v5_9, dependencies: [ - .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]) ], targets: [ TargetDescription( @@ -4199,42 +4412,47 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "App", - dependencies: [.product( - name: "A", - package: "apkg", - moduleAliases: [ - "Utils": "AUtils", - "FooUtils": "AFUtils", - ] - ), - .product( - name: "X", - package: "xpkg", - moduleAliases: ["FooUtils": "XFUtils"] - )], + dependencies: [ + .product( + name: "A", + package: "apkg", + moduleAliases: [ + "Utils": "AUtils", + "FooUtils": "AFUtils", + ] + ), + .product( + name: "X", + package: "xpkg", + moduleAliases: ["FooUtils": "XFUtils"] + ), + ], type: .executable - ), + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(7) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "A" && $0.module.moduleAliases?["Utils"] == "AUtils" && $0.module - .moduleAliases?["FooUtils"] == "AFUtils" + $0.module.name == "A" && $0.module.moduleAliases?["Utils"] == "AUtils" + && $0.module + .moduleAliases?["FooUtils"] == "AFUtils" } ) XCTAssertTrue( @@ -4260,7 +4478,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingChainedAliases3() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/aPkg/Sources/A/file.swift", "/aPkg/Sources/Utils/file.swift", "/bPkg/Sources/Utils/file.swift", @@ -4277,20 +4495,20 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "zpkg", path: "/zPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "ypkg", path: "/yPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( @@ -4302,7 +4520,7 @@ final class ModuleAliasingBuildTests: XCTestCase { .localSourceControl(path: "/zPkg", requirement: .upToNextMajor(from: "1.0.0")), ], products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["X"]) ], targets: [ TargetDescription( @@ -4319,17 +4537,17 @@ final class ModuleAliasingBuildTests: XCTestCase { moduleAliases: ["Utils": "ZUtils"] ), ] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "bpkg", path: "/bPkg", products: [ - ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Utils", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( @@ -4337,10 +4555,10 @@ final class ModuleAliasingBuildTests: XCTestCase { path: "/aPkg", toolsVersion: .v5_9, dependencies: [ - .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/bPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]) ], targets: [ TargetDescription( @@ -4368,45 +4586,50 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "App", - dependencies: [.product( - name: "A", - package: "apkg", - moduleAliases: [ - "Utils": "AUtils", - "FooUtils": "AFooUtils", - ] - ), - .product( - name: "X", - package: "xpkg", - moduleAliases: [ - "ZUtils": "XUtils", - "FooUtils": "XFooUtils", - ] - )], + dependencies: [ + .product( + name: "A", + package: "apkg", + moduleAliases: [ + "Utils": "AUtils", + "FooUtils": "AFooUtils", + ] + ), + .product( + name: "X", + package: "xpkg", + moduleAliases: [ + "ZUtils": "XUtils", + "FooUtils": "XFooUtils", + ] + ), + ], type: .executable - ), + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(7) XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "A" && $0.module.moduleAliases?["Utils"] == "AUtils" && $0.module - .moduleAliases?["FooUtils"] == "AFooUtils" + $0.module.name == "A" && $0.module.moduleAliases?["Utils"] == "AUtils" + && $0.module + .moduleAliases?["FooUtils"] == "AFooUtils" } ) XCTAssertTrue( @@ -4420,8 +4643,9 @@ final class ModuleAliasingBuildTests: XCTestCase { XCTAssertTrue( result.targetMap.values .contains { - $0.module.name == "X" && $0.module.moduleAliases?["ZUtils"] == "XUtils" && $0.module - .moduleAliases?["FooUtils"] == "XFooUtils" + $0.module.name == "X" && $0.module.moduleAliases?["ZUtils"] == "XUtils" + && $0.module + .moduleAliases?["FooUtils"] == "XFooUtils" } ) XCTAssertTrue( @@ -4439,7 +4663,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testModuleAliasingChainedAliases5() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/appPkg/Sources/App/main.swift", + "/appPkg/Sources/App/main.swift", "/xPkg/Sources/Utils/file.swift", "/yPkg/Sources/Utils/file.swift", "/zPkg/Sources/Utils/file.swift", @@ -4454,40 +4678,40 @@ final class ModuleAliasingBuildTests: XCTestCase { displayName: "apkg", path: "/aPkg", products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "wpkg", path: "/wPkg", products: [ - ProductDescription(name: "W", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "W", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "zpkg", path: "/zPkg", products: [ - ProductDescription(name: "Z", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Z", type: .library(.automatic), targets: ["Utils"]) ], targets: [ - TargetDescription(name: "Utils", dependencies: []), + TargetDescription(name: "Utils", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "ypkg", path: "/yPkg", dependencies: [ - .localSourceControl(path: "/zPkg", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/zPkg", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Y", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "Y", type: .library(.automatic), targets: ["Utils"]) ], targets: [ TargetDescription( @@ -4495,11 +4719,11 @@ final class ModuleAliasingBuildTests: XCTestCase { dependencies: [ .product( name: "Z", - package: "zpkg", // import ZUtils + package: "zpkg", // import ZUtils moduleAliases: ["Utils": "ZUtils"] - ), + ) ] - ), + ) ] ), Manifest.createFileSystemManifest( @@ -4510,7 +4734,7 @@ final class ModuleAliasingBuildTests: XCTestCase { .localSourceControl(path: "/wPkg", requirement: .upToNextMajor(from: "1.0.0")), ], products: [ - ProductDescription(name: "X", type: .library(.automatic), targets: ["Utils"]), + ProductDescription(name: "X", type: .library(.automatic), targets: ["Utils"]) ], targets: [ TargetDescription( @@ -4518,16 +4742,16 @@ final class ModuleAliasingBuildTests: XCTestCase { dependencies: [ .product( name: "Y", - package: "ypkg", // import YUtils + package: "ypkg", // import YUtils moduleAliases: ["ZUtils": "YUtils"] ), .product( name: "W", - package: "wpkg", // import WUtils + package: "wpkg", // import WUtils moduleAliases: ["Utils": "WUtils"] ), ] - ), + ) ] ), Manifest.createRootManifest( @@ -4540,35 +4764,39 @@ final class ModuleAliasingBuildTests: XCTestCase { targets: [ TargetDescription( name: "App", - dependencies: [.product( - name: "X", - package: "xpkg", - moduleAliases: [ - "Utils": "XUtils", - ] - ), - .product( - name: "A", - package: "apkg", - moduleAliases: [ - "Utils": "AUtils", - ] - )] - ), + dependencies: [ + .product( + name: "X", + package: "xpkg", + moduleAliases: [ + "Utils": "XUtils" + ] + ), + .product( + name: "A", + package: "apkg", + moduleAliases: [ + "Utils": "AUtils" + ] + ), + ] + ) ] ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkProductsCount(1) result.checkTargetsCount(6) XCTAssertTrue( @@ -4601,7 +4829,7 @@ final class ModuleAliasingBuildTests: XCTestCase { func testProductAliasingDoesNotBreakPackagesWithOlderToolsVersions() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/Lunch/Sources/MyTarget/file.swift", + "/Lunch/Sources/MyTarget/file.swift", "/Some/Sources/Some/file.swift", "/Other/Sources/Other/file.swift" ) @@ -4638,7 +4866,7 @@ final class ModuleAliasingBuildTests: XCTestCase { ) ], targets: [ - TargetDescription(name: "Some"), + TargetDescription(name: "Some") ] ), Manifest.createFileSystemManifest( @@ -4652,28 +4880,30 @@ final class ModuleAliasingBuildTests: XCTestCase { ) ], targets: [ - TargetDescription(name: "Other"), + TargetDescription(name: "Other") ] - ) + ), ], observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) - let result = try await BuildPlanResult(plan: try mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fs, - observabilityScope: observability.topScope - )) + let result = try await BuildPlanResult( + plan: try mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) result.checkTargetsCount(3) } func testProductAliasingWarnsIfPackageWithOlderToolsVersionIsPossibleCauseOfConflict() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/Lunch/Sources/MyTarget/file.swift", + "/Lunch/Sources/MyTarget/file.swift", "/Some/Sources/Some/file.swift", "/Other/Sources/Some/file.swift" ) @@ -4711,7 +4941,7 @@ final class ModuleAliasingBuildTests: XCTestCase { ) ], targets: [ - TargetDescription(name: "Some"), + TargetDescription(name: "Some") ] ), Manifest.createFileSystemManifest( @@ -4725,9 +4955,9 @@ final class ModuleAliasingBuildTests: XCTestCase { ) ], targets: [ - TargetDescription(name: "Some"), + TargetDescription(name: "Some") ] - ) + ), ], observabilityScope: observability.topScope ) diff --git a/Tests/BuildTests/PluginInvocationTests.swift b/Tests/BuildTests/PluginInvocationTests.swift index 7569ed86851..ecba9881ff3 100644 --- a/Tests/BuildTests/PluginInvocationTests.swift +++ b/Tests/BuildTests/PluginInvocationTests.swift @@ -10,16 +10,13 @@ // //===----------------------------------------------------------------------===// -@_spi(SwiftPMInternal) -import Basics +@_spi(SwiftPMInternal) import Basics -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -@testable import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) @testable import PackageGraph import PackageLoading -@_spi(SwiftPMInternal) -import PackageModel +@_spi(SwiftPMInternal) import PackageModel @testable import SPMBuildCore import _InternalBuildTestSupport @@ -36,8 +33,9 @@ import struct TSCUtility.SerializedDiagnostics final class PluginInvocationTests: XCTestCase { func testBasics() async throws { // Construct a canned file system and package graph with a single package and a library that uses a build tool plugin that invokes a tool. - let fileSystem = InMemoryFileSystem(emptyFiles: - "/Foo/Plugins/FooPlugin/source.swift", + let fileSystem = InMemoryFileSystem( + emptyFiles: + "/Foo/Plugins/FooPlugin/source.swift", "/Foo/Sources/FooTool/source.swift", "/Foo/Sources/FooToolLib/source.swift", "/Foo/Sources/Foo/source.swift", @@ -108,22 +106,24 @@ final class PluginInvocationTests: XCTestCase { // "FooTool{Lib}" duplicated as it's present for both build host and end target. do { - let buildPlanResult = try await BuildPlanResult(plan: mockBuildPlan( - graph: graph, - linkingParameters: .init( - shouldLinkStaticSwiftStdlib: true - ), - fileSystem: fileSystem, - observabilityScope: observability.topScope - )) + let buildPlanResult = try await BuildPlanResult( + plan: mockBuildPlan( + graph: graph, + linkingParameters: .init( + shouldLinkStaticSwiftStdlib: true + ), + fileSystem: fileSystem, + observabilityScope: observability.topScope + ) + ) buildPlanResult.checkProductsCount(3) - buildPlanResult.checkTargetsCount(5) // Note: plugins are not included here. + buildPlanResult.checkTargetsCount(5) // Note: plugins are not included here. buildPlanResult.check(destination: .target, for: "Foo") - + buildPlanResult.check(destination: .host, for: "FooTool") buildPlanResult.check(destination: .target, for: "FooTool") - + buildPlanResult.check(destination: .host, for: "FooToolLib") buildPlanResult.check(destination: .target, for: "FooToolLib") } @@ -135,7 +135,7 @@ final class PluginInvocationTests: XCTestCase { return try UserToolchain.default.targetTriple } } - + func compilePluginScript( sourceFiles: [AbsolutePath], pluginName: String, @@ -149,7 +149,7 @@ final class PluginInvocationTests: XCTestCase { completion(.failure(StringError("unimplemented"))) } } - + func runPluginScript( sourceFiles: [AbsolutePath], pluginName: String, @@ -173,48 +173,51 @@ final class PluginInvocationTests: XCTestCase { callbackQueue.sync { delegate.handleOutput(data: Data("Hello Plugin!".utf8)) } - + // Pretend it emitted a warning. try callbackQueue.sync { - let message = Data(""" - { "emitDiagnostic": { - "severity": "warning", - "message": "A warning", - "file": "/Foo/Sources/Foo/SomeFile.abc", - "line": 42 + let message = Data( + """ + { "emitDiagnostic": { + "severity": "warning", + "message": "A warning", + "file": "/Foo/Sources/Foo/SomeFile.abc", + "line": 42 + } } - } - """.utf8) + """.utf8 + ) try delegate.handleMessage(data: message, responder: { _ in }) } // Pretend it defined a build command. try callbackQueue.sync { - let message = Data(""" - { "defineBuildCommand": { - "configuration": { - "version": 2, - "displayName": "Do something", - "executable": "file:///bin/FooTool", - "arguments": [ - "-c", "/Foo/Sources/Foo/SomeFile.abc" - ], - "workingDirectory": "file:///Foo/Sources/Foo", - "environment": { - "X": "Y" + let message = Data( + """ + { "defineBuildCommand": { + "configuration": { + "version": 2, + "displayName": "Do something", + "executable": "file:///bin/FooTool", + "arguments": [ + "-c", "/Foo/Sources/Foo/SomeFile.abc" + ], + "workingDirectory": "file:///Foo/Sources/Foo", + "environment": { + "X": "Y" + }, }, - }, - "inputFiles": [ - ], - "outputFiles": [ - ] + "inputFiles": [ + ], + "outputFiles": [ + ] + } } - } - """.utf8) + """.utf8 + ) try delegate.handleMessage(data: message, responder: { _ in }) } - } - catch { + } catch { callbackQueue.sync { completion(.failure(error)) } @@ -273,51 +276,60 @@ final class PluginInvocationTests: XCTestCase { XCTAssertEqual(evalFirstResult.textOutput, "Hello Plugin!") } - + func testCompilationDiagnostics() async throws { try await testWithTemporaryDirectory { tmpPath in // Create a sample package with a library target and a plugin. let packageDir = tmpPath.appending(components: "MyPackage") try localFileSystem.createDirectory(packageDir, recursive: true) - try localFileSystem.writeFileContents(packageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.6 - import PackageDescription - let package = Package( - name: "MyPackage", - targets: [ - .target( - name: "MyLibrary", - plugins: [ - "MyPlugin", - ] - ), - .plugin( - name: "MyPlugin", - capability: .buildTool() - ), - ] - ) - """) - + try localFileSystem.writeFileContents( + packageDir.appending("Package.swift"), + string: """ + // swift-tools-version: 5.6 + import PackageDescription + let package = Package( + name: "MyPackage", + targets: [ + .target( + name: "MyLibrary", + plugins: [ + "MyPlugin", + ] + ), + .plugin( + name: "MyPlugin", + capability: .buildTool() + ), + ] + ) + """ + ) + let myLibraryTargetDir = packageDir.appending(components: "Sources", "MyLibrary") try localFileSystem.createDirectory(myLibraryTargetDir, recursive: true) - try localFileSystem.writeFileContents(myLibraryTargetDir.appending("library.swift"), string: """ - public func Foo() { } - """) - + try localFileSystem.writeFileContents( + myLibraryTargetDir.appending("library.swift"), + string: """ + public func Foo() { } + """ + ) + let myPluginTargetDir = packageDir.appending(components: "Plugins", "MyPlugin") try localFileSystem.createDirectory(myPluginTargetDir, recursive: true) - try localFileSystem.writeFileContents(myPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - @main struct MyBuildToolPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { - // missing return statement + try localFileSystem.writeFileContents( + myPluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + @main struct MyBuildToolPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { + // missing return statement + } } - } - """) + """ + ) // Load a workspace from the package. let observability = ObservabilitySystem.makeForTesting() @@ -327,7 +339,7 @@ final class PluginInvocationTests: XCTestCase { customManifestLoader: ManifestLoader(toolchain: UserToolchain.default), delegate: MockWorkspaceDelegate() ) - + // Load the root manifest. let rootInput = PackageGraphRootInput(packages: [packageDir], dependencies: []) let rootManifests = try await workspace.loadRootManifests( @@ -343,9 +355,9 @@ final class PluginInvocationTests: XCTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) XCTAssert(packageGraph.packages.count == 1, "\(packageGraph.packages)") - + // Find the build tool plugin. - let buildToolPlugin = try XCTUnwrap(packageGraph.packages.first?.modules.map(\.underlying).first{ $0.name == "MyPlugin" } as? PluginModule) + let buildToolPlugin = try XCTUnwrap(packageGraph.packages.first?.modules.map(\.underlying).first { $0.name == "MyPlugin" } as? PluginModule) XCTAssertEqual(buildToolPlugin.name, "MyPlugin") XCTAssertEqual(buildToolPlugin.capability, .buildTool) @@ -356,10 +368,10 @@ final class PluginInvocationTests: XCTestCase { cacheDir: pluginCacheDir, toolchain: try UserToolchain.default ) - + // Define a plugin compilation delegate that just captures the passed information. class Delegate: PluginScriptCompilerDelegate { - var commandLine: [String]? + var commandLine: [String]? var environment: Environment? var compiledResult: PluginCompilationResult? var cachedResult: PluginCompilationResult? @@ -402,7 +414,7 @@ final class PluginInvocationTests: XCTestCase { XCTAssertNotNil(delegate.environment) XCTAssertEqual(delegate.compiledResult, result) XCTAssertNil(delegate.cachedResult) - + // Check the serialized diagnostics. We should have an error. let diaFileContents = try localFileSystem.readFileContents(result.diagnosticsFile) let diagnosticsSet = try SerializedDiagnostics(bytes: diaFileContents) @@ -415,19 +427,22 @@ final class PluginInvocationTests: XCTestCase { } // Now replace the plugin script source with syntactically valid contents that still produces a warning. - try localFileSystem.writeFileContents(myPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - @main struct MyBuildToolPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { - var unused: Int - return [] + try localFileSystem.writeFileContents( + myPluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + @main struct MyBuildToolPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { + var unused: Int + return [] + } } - } - """) - + """ + ) + // Try to compile the fixed plugin. let firstExecModTime: Date do { @@ -523,17 +538,20 @@ final class PluginInvocationTests: XCTestCase { } // Now replace the plugin script source with syntactically valid contents that no longer produces a warning. - try localFileSystem.writeFileContents(myPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - @main struct MyBuildToolPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { - return [] + try localFileSystem.writeFileContents( + myPluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + @main struct MyBuildToolPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { + return [] + } } - } - """) + """ + ) // NTFS does not have nanosecond granularity (nor is this is a guaranteed file // system feature on all file systems). Add a sleep before the execution to ensure that we have sufficient @@ -566,7 +584,7 @@ final class PluginInvocationTests: XCTestCase { XCTAssertNotNil(delegate.environment) XCTAssertEqual(delegate.compiledResult, result) XCTAssertNil(delegate.cachedResult) - + // Check that the diagnostics no longer have a warning. let diaFileContents = try localFileSystem.readFileContents(result.diagnosticsFile) let diagnosticsSet = try SerializedDiagnostics(bytes: diaFileContents) @@ -582,17 +600,20 @@ final class PluginInvocationTests: XCTestCase { } // Now replace the plugin script source with a broken one again. - try localFileSystem.writeFileContents(myPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - @main struct MyBuildToolPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { - return nil // returning the wrong type + try localFileSystem.writeFileContents( + myPluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + @main struct MyBuildToolPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { + return nil // returning the wrong type + } } - } - """) + """ + ) // Recompile the plugin again. do { @@ -619,7 +640,7 @@ final class PluginInvocationTests: XCTestCase { XCTAssertNotNil(delegate.environment) XCTAssertEqual(delegate.compiledResult, result) XCTAssertNil(delegate.cachedResult) - + // Check the diagnostics. We should have a different error than the original one. let diaFileContents = try localFileSystem.readFileContents(result.diagnosticsFile) let diagnosticsSet = try SerializedDiagnostics(bytes: diaFileContents) @@ -641,63 +662,75 @@ final class PluginInvocationTests: XCTestCase { // Create a sample package with a library product and a plugin. let packageDir = tmpPath.appending(components: "MyPackage") try localFileSystem.createDirectory(packageDir, recursive: true) - try localFileSystem.writeFileContents(packageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.7 - import PackageDescription - let package = Package( - name: "MyPackage", - dependencies: [ - .package(path: "../FooPackage"), - ], - targets: [ - .plugin( - name: "MyPlugin", - capability: .buildTool(), + try localFileSystem.writeFileContents( + packageDir.appending("Package.swift"), + string: """ + // swift-tools-version: 5.7 + import PackageDescription + let package = Package( + name: "MyPackage", dependencies: [ - .product(name: "FooLib", package: "FooPackage"), + .package(path: "../FooPackage"), + ], + targets: [ + .plugin( + name: "MyPlugin", + capability: .buildTool(), + dependencies: [ + .product(name: "FooLib", package: "FooPackage"), + ] + ), ] - ), - ] + ) + """ ) - """) let myPluginTargetDir = packageDir.appending(components: "Plugins", "MyPlugin") try localFileSystem.createDirectory(myPluginTargetDir, recursive: true) - try localFileSystem.writeFileContents(myPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - import Foo - @main struct MyBuildToolPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { } - } - """) + try localFileSystem.writeFileContents( + myPluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + import Foo + @main struct MyBuildToolPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { } + } + """ + ) let fooPkgDir = tmpPath.appending(components: "FooPackage") try localFileSystem.createDirectory(fooPkgDir, recursive: true) - try localFileSystem.writeFileContents(fooPkgDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.7 - import PackageDescription - let package = Package( - name: "FooPackage", - products: [ - .library(name: "FooLib", - targets: ["Foo"]), - ], - targets: [ - .target( - name: "Foo", - dependencies: [] - ), - ] - ) - """) + try localFileSystem.writeFileContents( + fooPkgDir.appending("Package.swift"), + string: """ + // swift-tools-version: 5.7 + import PackageDescription + let package = Package( + name: "FooPackage", + products: [ + .library(name: "FooLib", + targets: ["Foo"]), + ], + targets: [ + .target( + name: "Foo", + dependencies: [] + ), + ] + ) + """ + ) let fooTargetDir = fooPkgDir.appending(components: "Sources", "Foo") try localFileSystem.createDirectory(fooTargetDir, recursive: true) - try localFileSystem.writeFileContents(fooTargetDir.appending("file.swift"), string: """ - public func foo() { } - """) + try localFileSystem.writeFileContents( + fooTargetDir.appending("file.swift"), + string: """ + public func foo() { } + """ + ) // Load a workspace from the package. let observability = ObservabilitySystem.makeForTesting() @@ -717,13 +750,16 @@ final class PluginInvocationTests: XCTestCase { XCTAssert(rootManifests.count == 1, "\(rootManifests)") // Load the package graph. - await XCTAssertAsyncThrowsError(try await workspace.loadPackageGraph( - rootInput: rootInput, - observabilityScope: observability.topScope - )) { error in + await XCTAssertAsyncThrowsError( + try await workspace.loadPackageGraph( + rootInput: rootInput, + observabilityScope: observability.topScope + ) + ) { error in var diagnosed = false if let realError = error as? PackageGraphError, - realError.description == "plugin 'MyPlugin' cannot depend on 'FooLib' of type 'library' from package 'foopackage'; this dependency is unsupported" { + realError.description == "plugin 'MyPlugin' cannot depend on 'FooLib' of type 'library' from package 'foopackage'; this dependency is unsupported" + { diagnosed = true } XCTAssertTrue(diagnosed) @@ -739,44 +775,53 @@ final class PluginInvocationTests: XCTestCase { // Create a sample package with a library target and a plugin. let packageDir = tmpPath.appending(components: "MyPackage") try localFileSystem.createDirectory(packageDir, recursive: true) - try localFileSystem.writeFileContents(packageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.7 - import PackageDescription - let package = Package( - name: "MyPackage", - targets: [ - .target( - name: "MyLibrary", - dependencies: [] - ), - .plugin( - name: "MyPlugin", - capability: .buildTool(), - dependencies: [ - "MyLibrary" - ] - ), - ] - ) - """) + try localFileSystem.writeFileContents( + packageDir.appending("Package.swift"), + string: """ + // swift-tools-version: 5.7 + import PackageDescription + let package = Package( + name: "MyPackage", + targets: [ + .target( + name: "MyLibrary", + dependencies: [] + ), + .plugin( + name: "MyPlugin", + capability: .buildTool(), + dependencies: [ + "MyLibrary" + ] + ), + ] + ) + """ + ) let myLibraryTargetDir = packageDir.appending(components: "Sources", "MyLibrary") try localFileSystem.createDirectory(myLibraryTargetDir, recursive: true) - try localFileSystem.writeFileContents(myLibraryTargetDir.appending("library.swift"), string: """ + try localFileSystem.writeFileContents( + myLibraryTargetDir.appending("library.swift"), + string: """ public func hello() { } - """) + """ + ) let myPluginTargetDir = packageDir.appending(components: "Plugins", "MyPlugin") try localFileSystem.createDirectory(myPluginTargetDir, recursive: true) - try localFileSystem.writeFileContents(myPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - import MyLibrary - @main struct MyBuildToolPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { } - } - """) + try localFileSystem.writeFileContents( + myPluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + import MyLibrary + @main struct MyBuildToolPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { } + } + """ + ) // Load a workspace from the package. let observability = ObservabilitySystem.makeForTesting() @@ -796,13 +841,16 @@ final class PluginInvocationTests: XCTestCase { XCTAssert(rootManifests.count == 1, "\(rootManifests)") // Load the package graph. - await XCTAssertAsyncThrowsError(try await workspace.loadPackageGraph( - rootInput: rootInput, - observabilityScope: observability.topScope - )) { error in + await XCTAssertAsyncThrowsError( + try await workspace.loadPackageGraph( + rootInput: rootInput, + observabilityScope: observability.topScope + ) + ) { error in var diagnosed = false if let realError = error as? PackageGraphError, - realError.description == "plugin 'MyPlugin' cannot depend on 'MyLibrary' of type 'library'; this dependency is unsupported" { + realError.description == "plugin 'MyPlugin' cannot depend on 'MyLibrary' of type 'library'; this dependency is unsupported" + { diagnosed = true } XCTAssertTrue(diagnosed) @@ -818,77 +866,89 @@ final class PluginInvocationTests: XCTestCase { // Create a sample package with a library target and a plugin. let packageDir = tmpPath.appending(components: "mypkg") try localFileSystem.createDirectory(packageDir, recursive: true) - try localFileSystem.writeFileContents(packageDir.appending("Package.swift"), string: """ - // swift-tools-version:5.7 - - import PackageDescription - - let package = Package( - name: "mypkg", - products: [ - .library( - name: "MyLib", - targets: ["MyLib"]) - ], - targets: [ - .target( - name: "MyLib", - plugins: [ - .plugin(name: "X") - ]), - .plugin( - name: "X", - capability: .buildTool(), - dependencies: [ "Y" ] - ), - .binaryTarget( - name: "Y", - path: "Binaries/Y.\(artifactBundleExtension)" - ), - ] - ) - """) + try localFileSystem.writeFileContents( + packageDir.appending("Package.swift"), + string: """ + // swift-tools-version:5.7 + + import PackageDescription + + let package = Package( + name: "mypkg", + products: [ + .library( + name: "MyLib", + targets: ["MyLib"]) + ], + targets: [ + .target( + name: "MyLib", + plugins: [ + .plugin(name: "X") + ]), + .plugin( + name: "X", + capability: .buildTool(), + dependencies: [ "Y" ] + ), + .binaryTarget( + name: "Y", + path: "Binaries/Y.\(artifactBundleExtension)" + ), + ] + ) + """ + ) let libTargetDir = packageDir.appending(components: "Sources", "MyLib") try localFileSystem.createDirectory(libTargetDir, recursive: true) - try localFileSystem.writeFileContents(libTargetDir.appending("file.swift"), string: """ - public struct MyUtilLib { - public let strings: [String] - public init(args: [String]) { - self.strings = args - } - } - """) + try localFileSystem.writeFileContents( + libTargetDir.appending("file.swift"), + string: """ + public struct MyUtilLib { + public let strings: [String] + public init(args: [String]) { + self.strings = args + } + } + """ + ) let depTargetDir = packageDir.appending(components: "Sources", "Y") try localFileSystem.createDirectory(depTargetDir, recursive: true) - try localFileSystem.writeFileContents(depTargetDir.appending("main.swift"), string: """ - struct Y { - func run() { - print("You passed us two arguments, argumentOne, and argumentTwo") - } - } - Y.main() - """) + try localFileSystem.writeFileContents( + depTargetDir.appending("main.swift"), + string: """ + struct Y { + func run() { + print("You passed us two arguments, argumentOne, and argumentTwo") + } + } + Y.main() + """ + ) let pluginTargetDir = packageDir.appending(components: "Plugins", "X") try localFileSystem.createDirectory(pluginTargetDir, recursive: true) - try localFileSystem.writeFileContents(pluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - @main struct X: BuildToolPlugin { - func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] { - [ - Command.prebuildCommand( - displayName: "X: Running Y before the build...", - executable: try context.tool(named: "Y").path, - arguments: [ "ARGUMENT_ONE", "ARGUMENT_TWO" ], - outputFilesDirectory: context.pluginWorkDirectory.appending("OUTPUT_FILES_DIRECTORY") - ) - ] - } - } - """) - + try localFileSystem.writeFileContents( + pluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + @main struct X: BuildToolPlugin { + func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] { + [ + Command.prebuildCommand( + displayName: "X: Running Y before the build...", + executable: try context.tool(named: "Y").path, + arguments: [ "ARGUMENT_ONE", "ARGUMENT_TWO" ], + outputFilesDirectory: context.pluginWorkDirectory.appending("OUTPUT_FILES_DIRECTORY") + ) + ] + } + } + """ + ) + let artifactVariants = [try UserToolchain.default.targetTriple].map { """ { "path": "Y", "supportedTriples": ["\($0.tripleString)"] } @@ -901,18 +961,18 @@ final class PluginInvocationTests: XCTestCase { try localFileSystem.writeFileContents( bundleMetadataPath, string: """ - { "schemaVersion": "1.0", - "artifacts": { - "Y": { - "type": "executable", - "version": "1.2.3", - "variants": [ - \(artifactVariants.joined(separator: ",")) - ] + { "schemaVersion": "1.0", + "artifacts": { + "Y": { + "type": "executable", + "version": "1.2.3", + "variants": [ + \(artifactVariants.joined(separator: ",")) + ] + } } } - } - """ + """ ) let binaryPath = bundlePath.appending(component: "Y") try localFileSystem.writeFileContents(binaryPath, string: "") @@ -943,7 +1003,7 @@ final class PluginInvocationTests: XCTestCase { XCTAssert(packageGraph.packages.count == 1, "\(packageGraph.packages)") // Find the build tool plugin. - let buildToolPlugin = try XCTUnwrap(packageGraph.packages.first?.modules.map(\.underlying).filter{ $0.name == "X" }.first as? PluginModule) + let buildToolPlugin = try XCTUnwrap(packageGraph.packages.first?.modules.map(\.underlying).filter { $0.name == "X" }.first as? PluginModule) XCTAssertEqual(buildToolPlugin.name, "X") XCTAssertEqual(buildToolPlugin.capability, .buildTool) @@ -980,7 +1040,6 @@ final class PluginInvocationTests: XCTestCase { } } - func testPrebuildPluginShouldNotUseExecTarget() async throws { // Only run the test if the environment in which we're running actually supports Swift concurrency (which the plugin APIs require). try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") @@ -989,75 +1048,87 @@ final class PluginInvocationTests: XCTestCase { // Create a sample package with a library target and a plugin. let packageDir = tmpPath.appending(components: "mypkg") try localFileSystem.createDirectory(packageDir, recursive: true) - try localFileSystem.writeFileContents(packageDir.appending("Package.swift"), string: """ - // swift-tools-version:5.7 - - import PackageDescription - - let package = Package( - name: "mypkg", - products: [ - .library( - name: "MyLib", - targets: ["MyLib"]) - ], - targets: [ - .target( - name: "MyLib", - plugins: [ - .plugin(name: "X") - ]), - .plugin( - name: "X", - capability: .buildTool(), - dependencies: [ "Y" ] - ), - .executableTarget( - name: "Y", - dependencies: []), - ] - ) - """) + try localFileSystem.writeFileContents( + packageDir.appending("Package.swift"), + string: """ + // swift-tools-version:5.7 + + import PackageDescription + + let package = Package( + name: "mypkg", + products: [ + .library( + name: "MyLib", + targets: ["MyLib"]) + ], + targets: [ + .target( + name: "MyLib", + plugins: [ + .plugin(name: "X") + ]), + .plugin( + name: "X", + capability: .buildTool(), + dependencies: [ "Y" ] + ), + .executableTarget( + name: "Y", + dependencies: []), + ] + ) + """ + ) let libTargetDir = packageDir.appending(components: "Sources", "MyLib") try localFileSystem.createDirectory(libTargetDir, recursive: true) - try localFileSystem.writeFileContents(libTargetDir.appending("file.swift"), string: """ - public struct MyUtilLib { - public let strings: [String] - public init(args: [String]) { - self.strings = args - } - } - """) + try localFileSystem.writeFileContents( + libTargetDir.appending("file.swift"), + string: """ + public struct MyUtilLib { + public let strings: [String] + public init(args: [String]) { + self.strings = args + } + } + """ + ) let depTargetDir = packageDir.appending(components: "Sources", "Y") try localFileSystem.createDirectory(depTargetDir, recursive: true) - try localFileSystem.writeFileContents(depTargetDir.appending("main.swift"), string: """ - struct Y { - func run() { - print("You passed us two arguments, argumentOne, and argumentTwo") - } - } - Y.main() - """) + try localFileSystem.writeFileContents( + depTargetDir.appending("main.swift"), + string: """ + struct Y { + func run() { + print("You passed us two arguments, argumentOne, and argumentTwo") + } + } + Y.main() + """ + ) let pluginTargetDir = packageDir.appending(components: "Plugins", "X") try localFileSystem.createDirectory(pluginTargetDir, recursive: true) - try localFileSystem.writeFileContents(pluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - @main struct X: BuildToolPlugin { - func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] { - [ - Command.prebuildCommand( - displayName: "X: Running Y before the build...", - executable: try context.tool(named: "Y").path, - arguments: [ "ARGUMENT_ONE", "ARGUMENT_TWO" ], - outputFilesDirectory: context.pluginWorkDirectory.appending("OUTPUT_FILES_DIRECTORY") - ) - ] - } - } - """) + try localFileSystem.writeFileContents( + pluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + @main struct X: BuildToolPlugin { + func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] { + [ + Command.prebuildCommand( + displayName: "X: Running Y before the build...", + executable: try context.tool(named: "Y").path, + arguments: [ "ARGUMENT_ONE", "ARGUMENT_TWO" ], + outputFilesDirectory: context.pluginWorkDirectory.appending("OUTPUT_FILES_DIRECTORY") + ) + ] + } + } + """ + ) // Load a workspace from the package. let observability = ObservabilitySystem.makeForTesting() @@ -1085,7 +1156,7 @@ final class PluginInvocationTests: XCTestCase { XCTAssert(packageGraph.packages.count == 1, "\(packageGraph.packages)") // Find the build tool plugin. - let buildToolPlugin = try XCTUnwrap(packageGraph.packages.first?.modules.map(\.underlying).filter{ $0.name == "X" }.first as? PluginModule) + let buildToolPlugin = try XCTUnwrap(packageGraph.packages.first?.modules.map(\.underlying).filter { $0.name == "X" }.first as? PluginModule) XCTAssertEqual(buildToolPlugin.name, "X") XCTAssertEqual(buildToolPlugin.capability, .buildTool) @@ -1131,120 +1202,140 @@ final class PluginInvocationTests: XCTestCase { // Create a sample package with a library target and a plugin. let packageDir = tmpPath.appending(components: "MyPackage") try localFileSystem.createDirectory(packageDir, recursive: true) - try localFileSystem.writeFileContents(packageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.7 - import PackageDescription - let package = Package( - name: "MyPackage", - dependencies: [ - .package(path: "../OtherPackage"), - ], - targets: [ - .target( - name: "MyLibrary", - dependencies: [.product(name: "OtherPlugin", package: "OtherPackage")] - ), - .plugin( - name: "XPlugin", - capability: .buildTool() - ), - .plugin( - name: "YPlugin", - capability: .command( - intent: .custom(verb: "YPlugin", description: "Plugin example"), - permissions: [] + try localFileSystem.writeFileContents( + packageDir.appending("Package.swift"), + string: """ + // swift-tools-version: 5.7 + import PackageDescription + let package = Package( + name: "MyPackage", + dependencies: [ + .package(path: "../OtherPackage"), + ], + targets: [ + .target( + name: "MyLibrary", + dependencies: [.product(name: "OtherPlugin", package: "OtherPackage")] + ), + .plugin( + name: "XPlugin", + capability: .buildTool() + ), + .plugin( + name: "YPlugin", + capability: .command( + intent: .custom(verb: "YPlugin", description: "Plugin example"), + permissions: [] + ) ) - ) - ] - ) - """) + ] + ) + """ + ) let myLibraryTargetDir = packageDir.appending(components: "Sources", "MyLibrary") try localFileSystem.createDirectory(myLibraryTargetDir, recursive: true) - try localFileSystem.writeFileContents(myLibraryTargetDir.appending("library.swift"), string: """ + try localFileSystem.writeFileContents( + myLibraryTargetDir.appending("library.swift"), + string: """ public func hello() { } - """) + """ + ) let xPluginTargetDir = packageDir.appending(components: "Plugins", "XPlugin") try localFileSystem.createDirectory(xPluginTargetDir, recursive: true) - try localFileSystem.writeFileContents(xPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - import XcodeProjectPlugin - @main struct XBuildToolPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { } - } - """) + try localFileSystem.writeFileContents( + xPluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + import XcodeProjectPlugin + @main struct XBuildToolPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { } + } + """ + ) let yPluginTargetDir = packageDir.appending(components: "Plugins", "YPlugin") try localFileSystem.createDirectory(yPluginTargetDir, recursive: true) - try localFileSystem.writeFileContents(yPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - import Foundation - @main struct YPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { } - } - """) - + try localFileSystem.writeFileContents( + yPluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + import Foundation + @main struct YPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { } + } + """ + ) ////// let otherPackageDir = tmpPath.appending(components: "OtherPackage") try localFileSystem.createDirectory(otherPackageDir, recursive: true) - try localFileSystem.writeFileContents(otherPackageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.7 - import PackageDescription - let package = Package( - name: "OtherPackage", - products: [ - .plugin( - name: "OtherPlugin", - targets: ["QPlugin"]) - ], - targets: [ - .plugin( - name: "QPlugin", - capability: .buildTool() - ), - .plugin( - name: "RPlugin", - capability: .command( - intent: .custom(verb: "RPlugin", description: "Plugin example"), - permissions: [] + try localFileSystem.writeFileContents( + otherPackageDir.appending("Package.swift"), + string: """ + // swift-tools-version: 5.7 + import PackageDescription + let package = Package( + name: "OtherPackage", + products: [ + .plugin( + name: "OtherPlugin", + targets: ["QPlugin"]) + ], + targets: [ + .plugin( + name: "QPlugin", + capability: .buildTool() + ), + .plugin( + name: "RPlugin", + capability: .command( + intent: .custom(verb: "RPlugin", description: "Plugin example"), + permissions: [] + ) ) - ) - ] - ) - """) + ] + ) + """ + ) let qPluginTargetDir = otherPackageDir.appending(components: "Plugins", "QPlugin") try localFileSystem.createDirectory(qPluginTargetDir, recursive: true) - try localFileSystem.writeFileContents(qPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - import XcodeProjectPlugin - #if canImport(ModuleFoundViaExtraSearchPaths) - import ModuleFoundViaExtraSearchPaths - #endif - @main struct QBuildToolPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { } - } - """) - + try localFileSystem.writeFileContents( + qPluginTargetDir.appending("plugin.swift"), + string: """ + import PackagePlugin + import XcodeProjectPlugin + #if canImport(ModuleFoundViaExtraSearchPaths) + import ModuleFoundViaExtraSearchPaths + #endif + @main struct QBuildToolPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { } + } + """ + ) + // Create a valid swift interface file that can be detected via `canImport()`. let fakeExtraModulesDir = tmpPath.appending("ExtraModules") try localFileSystem.createDirectory(fakeExtraModulesDir, recursive: true) let fakeExtraModuleFile = fakeExtraModulesDir.appending("ModuleFoundViaExtraSearchPaths.swiftinterface") - try localFileSystem.writeFileContents(fakeExtraModuleFile, string: """ - // swift-interface-format-version: 1.0 - // swift-module-flags: -module-name ModuleFoundViaExtraSearchPaths - """) - + try localFileSystem.writeFileContents( + fakeExtraModuleFile, + string: """ + // swift-interface-format-version: 1.0 + // swift-module-flags: -module-name ModuleFoundViaExtraSearchPaths + """ + ) + ///////// // Load a workspace from the package. let observability = ObservabilitySystem.makeForTesting() @@ -1283,21 +1374,18 @@ final class PluginInvocationTests: XCTestCase { XCTAssertNotNil(entry["XPlugin"]) let XPluginPossibleImports1 = ["PackagePlugin", "XcodeProjectPlugin"] let XPluginPossibleImports2 = ["PackagePlugin", "XcodeProjectPlugin", "_SwiftConcurrencyShims"] - XCTAssertTrue(entry["XPlugin"] == XPluginPossibleImports1 || - entry["XPlugin"] == XPluginPossibleImports2) + XCTAssertTrue(entry["XPlugin"] == XPluginPossibleImports1 || entry["XPlugin"] == XPluginPossibleImports2) let YPluginPossibleImports1 = ["PackagePlugin", "Foundation"] let YPluginPossibleImports2 = ["PackagePlugin", "Foundation", "_SwiftConcurrencyShims"] - XCTAssertTrue(entry["YPlugin"] == YPluginPossibleImports1 || - entry["YPlugin"] == YPluginPossibleImports2) + XCTAssertTrue(entry["YPlugin"] == YPluginPossibleImports1 || entry["YPlugin"] == YPluginPossibleImports2) count += 1 } else if pkg.description == "otherpackage" { XCTAssertNotNil(dict[pkg]?["QPlugin"]) let possibleImports1 = ["PackagePlugin", "XcodeProjectPlugin", "ModuleFoundViaExtraSearchPaths"] let possibleImports2 = ["PackagePlugin", "XcodeProjectPlugin", "ModuleFoundViaExtraSearchPaths", "_SwiftConcurrencyShims"] - XCTAssertTrue(entry["QPlugin"] == possibleImports1 || - entry["QPlugin"] == possibleImports2) + XCTAssertTrue(entry["QPlugin"] == possibleImports1 || entry["QPlugin"] == possibleImports2) count += 1 } } @@ -1309,7 +1397,7 @@ final class PluginInvocationTests: XCTestCase { func checkParseArtifactsPlatformCompatibility( artifactSupportedTriples: [Triple], hostTriple: Triple - ) async throws -> [ResolvedModule.ID: [BuildToolPluginInvocationResult]] { + ) async throws -> [ResolvedModule.ID: [BuildToolPluginInvocationResult]] { // Only run the test if the environment in which we're running actually supports Swift concurrency (which the plugin APIs require). try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") @@ -1317,60 +1405,63 @@ final class PluginInvocationTests: XCTestCase { // Create a sample package with a library target and a plugin. let packageDir = tmpPath.appending(components: "MyPackage") try localFileSystem.createDirectory(packageDir, recursive: true) - try localFileSystem.writeFileContents(packageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.7 - import PackageDescription - let package = Package( - name: "MyPackage", - dependencies: [ - ], - targets: [ - .target( - name: "MyLibrary", - plugins: [ - "Foo", - ] - ), - .plugin( - name: "Foo", - capability: .buildTool(), - dependencies: [ - .target(name: "LocalBinaryTool"), - ] + try localFileSystem.writeFileContents( + packageDir.appending("Package.swift"), + string: """ + // swift-tools-version: 5.7 + import PackageDescription + let package = Package( + name: "MyPackage", + dependencies: [ + ], + targets: [ + .target( + name: "MyLibrary", + plugins: [ + "Foo", + ] ), - .binaryTarget( - name: "LocalBinaryTool", - path: "Binaries/LocalBinaryTool.\(artifactBundleExtension)" - ), - ] - ) - """) + .plugin( + name: "Foo", + capability: .buildTool(), + dependencies: [ + .target(name: "LocalBinaryTool"), + ] + ), + .binaryTarget( + name: "LocalBinaryTool", + path: "Binaries/LocalBinaryTool.\(artifactBundleExtension)" + ), + ] + ) + """ + ) let libDir = packageDir.appending(components: "Sources", "MyLibrary") try localFileSystem.createDirectory(libDir, recursive: true) try localFileSystem.writeFileContents( libDir.appending(components: "library.swift"), string: """ - public func myLib() { } - """ + public func myLib() { } + """ ) let myPluginTargetDir = packageDir.appending(components: "Plugins", "Foo") try localFileSystem.createDirectory(myPluginTargetDir, recursive: true) let content = """ - import PackagePlugin - @main struct FooPlugin: BuildToolPlugin { - func createBuildCommands( - context: PluginContext, - target: Target - ) throws -> [Command] { - print("Looking for LocalBinaryTool...") - let localBinaryTool = try context.tool(named: "LocalBinaryTool") - print("... found it at \\(localBinaryTool.path)") - return [.buildCommand(displayName: "", executable: localBinaryTool.path, arguments: [], inputFiles: [], outputFiles: [])] - } - } - """ + import PackagePlugin + @main struct FooPlugin: BuildToolPlugin { + func createBuildCommands( + context: PluginContext, + target: Target + ) throws -> [Command] { + print("Looking for LocalBinaryTool...") + let localBinaryTool = try context.tool(named: "LocalBinaryTool") + print("... found it at \\(localBinaryTool.path)") + return [.buildCommand(displayName: "", executable: localBinaryTool.path, arguments: [], inputFiles: [], outputFiles: [])] + } + } + """ try localFileSystem.writeFileContents(myPluginTargetDir.appending("plugin.swift"), string: content) let artifactVariants = artifactSupportedTriples.map { """ @@ -1387,18 +1478,18 @@ final class PluginInvocationTests: XCTestCase { try localFileSystem.writeFileContents( bundleMetadataPath, string: """ - { "schemaVersion": "1.0", - "artifacts": { - "LocalBinaryTool": { - "type": "executable", - "version": "1.2.3", - "variants": [ - \(artifactVariants.joined(separator: ",")) - ] + { "schemaVersion": "1.0", + "artifacts": { + "LocalBinaryTool": { + "type": "executable", + "version": "1.2.3", + "variants": [ + \(artifactVariants.joined(separator: ",")) + ] + } } } - } - """ + """ ) // Load a workspace from the package. let observability = ObservabilitySystem.makeForTesting() @@ -1425,10 +1516,12 @@ final class PluginInvocationTests: XCTestCase { XCTAssertNoDiagnostics(observability.diagnostics) // Find the build tool plugin. - let buildToolPlugin = try XCTUnwrap(packageGraph.packages.first?.modules - .map(\.underlying) - .filter { $0.name == "Foo" } - .first as? PluginModule) + let buildToolPlugin = try XCTUnwrap( + packageGraph.packages.first?.modules + .map(\.underlying) + .filter { $0.name == "Foo" } + .first as? PluginModule + ) XCTAssertEqual(buildToolPlugin.name, "Foo") XCTAssertEqual(buildToolPlugin.capability, .buildTool) @@ -1477,8 +1570,9 @@ final class PluginInvocationTests: XCTestCase { var checked = false let result = try await checkParseArtifactsPlatformCompatibility(artifactSupportedTriples: artifactSupportedTriples, hostTriple: hostTriple) if let pluginResult = result.first, - let diag = pluginResult.value.first?.diagnostics, - diag.description == "[[error]: Tool ‘LocalBinaryTool’ is not supported on the target platform]" { + let diag = pluginResult.value.first?.diagnostics, + diag.description == "[[error]: Tool ‘LocalBinaryTool’ is not supported on the target platform]" + { checked = true } XCTAssertTrue(checked) @@ -1486,18 +1580,18 @@ final class PluginInvocationTests: XCTestCase { func testParseArtifactsDoesNotCheckPlatformVersion() async throws { #if !os(macOS) - throw XCTSkip("platform versions are only available if the host is macOS") + throw XCTSkip("platform versions are only available if the host is macOS") #else - let hostTriple = try UserToolchain.default.targetTriple - let artifactSupportedTriples = try [Triple("\(hostTriple.withoutVersion().tripleString)20.0")] - - let result = try await checkParseArtifactsPlatformCompatibility(artifactSupportedTriples: artifactSupportedTriples, hostTriple: hostTriple) - result.forEach { - $0.value.forEach { - XCTAssertTrue($0.succeeded, "plugin unexpectedly failed") - XCTAssertEqual($0.diagnostics.map { $0.message }, [], "plugin produced unexpected diagnostics") + let hostTriple = try UserToolchain.default.targetTriple + let artifactSupportedTriples = try [Triple("\(hostTriple.withoutVersion().tripleString)20.0")] + + let result = try await checkParseArtifactsPlatformCompatibility(artifactSupportedTriples: artifactSupportedTriples, hostTriple: hostTriple) + result.forEach { + $0.value.forEach { + XCTAssertTrue($0.succeeded, "plugin unexpectedly failed") + XCTAssertEqual($0.diagnostics.map { $0.message }, [], "plugin produced unexpected diagnostics") + } } - } #endif } @@ -1531,10 +1625,11 @@ final class PluginInvocationTests: XCTestCase { plugins.forEach { result.insert($0) } } - var pluginInvocationResults: [ResolvedModule.ID: ( - target: ResolvedModule, - results: [BuildToolPluginInvocationResult] - )] = [:] + var pluginInvocationResults: + [ResolvedModule.ID: ( + target: ResolvedModule, + results: [BuildToolPluginInvocationResult] + )] = [:] let pluginConfiguration = PluginConfiguration( scriptRunner: pluginScriptRunner, @@ -1581,5 +1676,5 @@ extension BuildPlanResult { $0.module.name == target && $0.destination == destination } XCTAssertEqual(targets.count, 1, file: file, line: line) - } + } } diff --git a/Tests/BuildTests/PluginsBuildPlanTests.swift b/Tests/BuildTests/PluginsBuildPlanTests.swift index 51bce014719..ac5d0eda179 100644 --- a/Tests/BuildTests/PluginsBuildPlanTests.swift +++ b/Tests/BuildTests/PluginsBuildPlanTests.swift @@ -37,17 +37,17 @@ struct PluginsBuildPlanTests { config: BuildConfiguration, ) async throws { try await withKnownIssue(isIntermittent: true) { - try await fixture(name: "Miscellaneous/Plugins/MySourceGenPlugin") { fixturePath in - let (stdout, _) = try await executeSwiftBuild( - fixturePath, - configuration: config, - buildSystem: .native - ) - #expect(stdout.contains("Build complete!")) - // FIXME: This is temporary until build of plugin tools is extracted into its own command. - #expect(localFileSystem.exists(fixturePath.appending(RelativePath(".build/plugin-tools.db")))) - #expect(localFileSystem.exists(fixturePath.appending(RelativePath(".build/build.db")))) - } + try await fixture(name: "Miscellaneous/Plugins/MySourceGenPlugin") { fixturePath in + let (stdout, _) = try await executeSwiftBuild( + fixturePath, + configuration: config, + buildSystem: .native + ) + #expect(stdout.contains("Build complete!")) + // FIXME: This is temporary until build of plugin tools is extracted into its own command. + #expect(localFileSystem.exists(fixturePath.appending(RelativePath(".build/plugin-tools.db")))) + #expect(localFileSystem.exists(fixturePath.appending(RelativePath(".build/build.db")))) + } } when: { ProcessInfo.hostOperatingSystem == .windows } @@ -94,11 +94,11 @@ struct PluginsBuildPlanTests { } let pluginToolName: String switch buildData.buildSystem { - case .native: + case .native: pluginToolName = "plugintool-tool" - case .swiftbuild: + case .swiftbuild: pluginToolName = "plugintool" - case .xcode: + case .xcode: pluginToolName = "" Issue.record("Test has not been updated for this build system") } @@ -164,13 +164,13 @@ struct PluginsBuildPlanTests { let pluginToolName: String let pluginToolBinPath: AbsolutePath switch buildData.buildSystem { - case .native: + case .native: pluginToolName = "plugintool-tool" pluginToolBinPath = hostBinPath - case .swiftbuild: + case .swiftbuild: pluginToolName = "plugintool" pluginToolBinPath = targetBinPath - case .xcode: + case .xcode: pluginToolName = "" pluginToolBinPath = AbsolutePath("/") Issue.record("Test has not been updated for this build system") diff --git a/Tests/BuildTests/PrepareForIndexTests.swift b/Tests/BuildTests/PrepareForIndexTests.swift index f49e09cc851..06f24aeedda 100644 --- a/Tests/BuildTests/PrepareForIndexTests.swift +++ b/Tests/BuildTests/PrepareForIndexTests.swift @@ -19,8 +19,7 @@ import _InternalTestSupport import TSCBasic import XCTest import class Basics.ObservabilitySystem -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import func PackageGraph.loadModulesGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import func PackageGraph.loadModulesGraph import class PackageModel.Manifest import struct PackageGraph.ModulesGraph import struct PackageModel.TargetDescription @@ -65,9 +64,11 @@ class PrepareForIndexTests: XCTestCase { XCTAssertEqual(toolCommands.count, 1) let toolSwiftc = try XCTUnwrap(toolCommands.first?.tool as? SwiftCompilerTool) XCTAssertFalse(toolSwiftc.otherArguments.contains("-experimental-skip-all-function-bodies")) - XCTAssertTrue(toolSwiftc.outputs.contains(where: { - $0.name.hasSuffix(".swift.o") - })) + XCTAssertTrue( + toolSwiftc.outputs.contains(where: { + $0.name.hasSuffix(".swift.o") + }) + ) // Make sure only object files for tools are built XCTAssertTrue( @@ -95,10 +96,10 @@ class PrepareForIndexTests: XCTestCase { XCTAssertTrue(manifest.targets.keys.contains(name)) } - func testEnableTestingSetup() throws-> (fs: InMemoryFileSystem, observability: TestingObservability, graph: ModulesGraph) { + func testEnableTestingSetup() throws -> (fs: InMemoryFileSystem, observability: TestingObservability, graph: ModulesGraph) { let fs = InMemoryFileSystem( emptyFiles: - "/Pkg/Sources/lib/lib.swift", + "/Pkg/Sources/lib/lib.swift", "/Pkg/Tests/test/TestCase.swift" ) @@ -114,7 +115,7 @@ class PrepareForIndexTests: XCTestCase { TargetDescription(name: "lib", dependencies: []), TargetDescription(name: "test", dependencies: ["lib"], type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -139,21 +140,25 @@ class PrepareForIndexTests: XCTestCase { let debugBuilder = LLBuildManifestBuilder(debugPlan, fileSystem: fs, observabilityScope: scope) let debugManifest = try debugBuilder.generateManifest(at: "/manifest") - XCTAssertNil(debugManifest.commands.values.first(where: { - guard let swiftCommand = $0.tool as? SwiftCompilerTool, - swiftCommand.outputs.contains(where: { $0.name.hasSuffix("/lib.swiftmodule")}) - else { - return false - } - return swiftCommand.otherArguments.contains("-experimental-skip-non-exportable-decls") - && !swiftCommand.otherArguments.contains("-enable-testing") - })) + XCTAssertNil( + debugManifest.commands.values.first(where: { + guard let swiftCommand = $0.tool as? SwiftCompilerTool, + swiftCommand.outputs.contains(where: { $0.name.hasSuffix("/lib.swiftmodule") }) + else { + return false + } + return swiftCommand.otherArguments.contains("-experimental-skip-non-exportable-decls") + && !swiftCommand.otherArguments.contains("-enable-testing") + }) + ) } func testEnableTestingReleaseConfiguration() async throws { - try XCTSkipOnWindows(because: """ - Assertion failure. ("0") is not equal to ("1"). Possibly related to https://github.com/swiftlang/swift-package-manager/issues/8511 - """) + try XCTSkipOnWindows( + because: """ + Assertion failure. ("0") is not equal to ("1"). Possibly related to https://github.com/swiftlang/swift-package-manager/issues/8511 + """ + ) let (fs, observability, graph) = try self.testEnableTestingSetup() let scope = observability.topScope @@ -171,15 +176,18 @@ class PrepareForIndexTests: XCTestCase { let releaseBuilder = LLBuildManifestBuilder(releasePlan, fileSystem: fs, observabilityScope: scope) let releaseManifest = try releaseBuilder.generateManifest(at: "/manifest") - XCTAssertEqual(releaseManifest.commands.values.filter({ - guard let swiftCommand = $0.tool as? SwiftCompilerTool, - swiftCommand.outputs.contains(where: { $0.name.hasSuffix("/lib.swiftmodule")}) - else { - return false - } - return swiftCommand.otherArguments.contains("-experimental-skip-non-exportable-decls") - && !swiftCommand.otherArguments.contains("-enable-testing") - }).count, 1) + XCTAssertEqual( + releaseManifest.commands.values.filter({ + guard let swiftCommand = $0.tool as? SwiftCompilerTool, + swiftCommand.outputs.contains(where: { $0.name.hasSuffix("/lib.swiftmodule") }) + else { + return false + } + return swiftCommand.otherArguments.contains("-experimental-skip-non-exportable-decls") + && !swiftCommand.otherArguments.contains("-enable-testing") + }).count, + 1 + ) } func testPrepareNoLazy() async throws { diff --git a/Tests/BuildTests/ProductBuildDescriptionTests.swift b/Tests/BuildTests/ProductBuildDescriptionTests.swift index 5674142e10d..27de83c011b 100644 --- a/Tests/BuildTests/ProductBuildDescriptionTests.swift +++ b/Tests/BuildTests/ProductBuildDescriptionTests.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@testable -import Build +@testable import Build import class Basics.InMemoryFileSystem import class Basics.ObservabilitySystem @@ -19,11 +18,9 @@ import class Basics.ObservabilitySystem import class PackageModel.Manifest import struct PackageModel.TargetDescription -@testable -import struct PackageGraph.ResolvedProduct +@testable import struct PackageGraph.ResolvedProduct -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import func PackageGraph.loadModulesGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import func PackageGraph.loadModulesGraph import func _InternalTestSupport.mockBuildParameters import func _InternalTestSupport.XCTAssertNoDiagnostics @@ -33,7 +30,7 @@ final class ProductBuildDescriptionTests: XCTestCase { func testEmbeddedProducts() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Pkg/Sources/exe/main.swift" + "/Pkg/Sources/exe/main.swift" ) let observability = ObservabilitySystem.makeForTesting() @@ -47,9 +44,9 @@ final class ProductBuildDescriptionTests: XCTestCase { TargetDescription( name: "exe", settings: [.init(tool: .swift, kind: .enableExperimentalFeature("Embedded"))] - ), + ) ] - ), + ) ], observabilityScope: observability.topScope ) diff --git a/Tests/BuildTests/SwiftCompilerOutputParserTests.swift b/Tests/BuildTests/SwiftCompilerOutputParserTests.swift index f8fc46614f3..85473a3889a 100644 --- a/Tests/BuildTests/SwiftCompilerOutputParserTests.swift +++ b/Tests/BuildTests/SwiftCompilerOutputParserTests.swift @@ -20,133 +20,171 @@ struct SwiftCompilerOutputParserTests { let delegate = MockSwiftCompilerOutputParserDelegate() let parser = SwiftCompilerOutputParser(targetName: "dummy", delegate: delegate) - parser.parse(bytes: """ - 338 - { - "kind": "began", - "name": "compile", - "inputs": [ - "test.swift" - ], - "outputs": [ + parser.parse( + bytes: """ + 338 { - "type": "object", - "path": "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test-77d991.o" + "kind": "began", + "name": "compile", + "inputs": [ + "test.swift" + ], + "outputs": [ + { + "type": "object", + "path": "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test-77d991.o" + } + ], + "pid": 22698, + "command_executable": "swift", + "command_arguments" : ["-frontend", "-c", "-primary-file", "test.swift"] } - ], - "pid": 22698, - "command_executable": "swift", - "command_arguments" : ["-frontend", "-c", "-primary-file", "test.swift"] - } - 117 - { - "kind": "finished", - "name": "compile", - "pid": 22698, - "exit-status": 1, - "output": "error: it failed :-(" - } - 233 - { - "kind": "skipped", - "name": "compile", - "inputs": [ - "test2.swift" - ], - "outputs": [ + 117 { - "type": "object", - "path": "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test2-77d991.o" + "kind": "finished", + "name": "compile", + "pid": 22698, + "exit-status": 1, + "output": "error: it failed :-(" } - ], - "pid": 58776 - } - 250 - { - "kind": "began", - "name": "verify-module-interface", - "inputs": [ - "main.swiftinterface" - ], - "pid": 31337, - "command_executable": "swift", - "command_arguments" : ["-frontend", "-typecheck-module-from-interface", "main.swiftinterface"] - } - 299 - { - "kind": "began", - "name": "link", - "inputs": [ - "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test-77d991.o" - ], - "outputs": [ + 233 { - "type": "image", - "path": "test" + "kind": "skipped", + "name": "compile", + "inputs": [ + "test2.swift" + ], + "outputs": [ + { + "type": "object", + "path": "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test2-77d991.o" + } + ], + "pid": 58776 } - ], - "pid": 22699, - "command_executable": "ld", - "command_arguments" : ["-o", "option", "test"] - } - 119 - { - "kind": "signalled", - "name": "link", - "pid": 22699, - "error-message": "Segmentation fault: 11", - "signal": 4 - } - - """.utf8) - - delegate.assert(messages: [ - SwiftCompilerMessage( - name: "compile", - kind: .began(.init( - pid: 22698, - inputs: ["test.swift"], - outputs: [.init( - type: "object", - path: "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test-77d991.o")], - commandExecutable: "swift", - commandArguments: ["-frontend", "-c", "-primary-file", "test.swift"]))), - SwiftCompilerMessage( - name: "compile", - kind: .finished(.init( - pid: 22698, - output: "error: it failed :-("))), - SwiftCompilerMessage( - name: "compile", - kind: .skipped(.init( - inputs: ["test2.swift"], - outputs: [.init( - type: "object", - path: "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test2-77d991.o")]))), - SwiftCompilerMessage( - name: "verify-module-interface", - kind: .began(.init( - pid: 31337, - inputs: ["main.swiftinterface"], - outputs: nil, - commandExecutable: "swift", - commandArguments: ["-frontend", "-typecheck-module-from-interface", "main.swiftinterface"]))), - SwiftCompilerMessage( - name: "link", - kind: .began(.init( - pid: 22699, - inputs: ["/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test-77d991.o"], - outputs: [.init( - type: "image", - path: "test")], - commandExecutable: "ld", - commandArguments: ["-o", "option", "test"]))), - SwiftCompilerMessage( - name: "link", - kind: .signalled(.init( - pid: 22699, - output: nil))) - ], errorDescription: nil) + 250 + { + "kind": "began", + "name": "verify-module-interface", + "inputs": [ + "main.swiftinterface" + ], + "pid": 31337, + "command_executable": "swift", + "command_arguments" : ["-frontend", "-typecheck-module-from-interface", "main.swiftinterface"] + } + 299 + { + "kind": "began", + "name": "link", + "inputs": [ + "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test-77d991.o" + ], + "outputs": [ + { + "type": "image", + "path": "test" + } + ], + "pid": 22699, + "command_executable": "ld", + "command_arguments" : ["-o", "option", "test"] + } + 119 + { + "kind": "signalled", + "name": "link", + "pid": 22699, + "error-message": "Segmentation fault: 11", + "signal": 4 + } + + """.utf8 + ) + + delegate.assert( + messages: [ + SwiftCompilerMessage( + name: "compile", + kind: .began( + .init( + pid: 22698, + inputs: ["test.swift"], + outputs: [ + .init( + type: "object", + path: "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test-77d991.o" + ) + ], + commandExecutable: "swift", + commandArguments: ["-frontend", "-c", "-primary-file", "test.swift"] + ) + ) + ), + SwiftCompilerMessage( + name: "compile", + kind: .finished( + .init( + pid: 22698, + output: "error: it failed :-(" + ) + ) + ), + SwiftCompilerMessage( + name: "compile", + kind: .skipped( + .init( + inputs: ["test2.swift"], + outputs: [ + .init( + type: "object", + path: "/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test2-77d991.o" + ) + ] + ) + ) + ), + SwiftCompilerMessage( + name: "verify-module-interface", + kind: .began( + .init( + pid: 31337, + inputs: ["main.swiftinterface"], + outputs: nil, + commandExecutable: "swift", + commandArguments: ["-frontend", "-typecheck-module-from-interface", "main.swiftinterface"] + ) + ) + ), + SwiftCompilerMessage( + name: "link", + kind: .began( + .init( + pid: 22699, + inputs: ["/var/folders/yc/rgflx8m11p5d71k1ydy0l_pr0000gn/T/test-77d991.o"], + outputs: [ + .init( + type: "image", + path: "test" + ) + ], + commandExecutable: "ld", + commandArguments: ["-o", "option", "test"] + ) + ) + ), + SwiftCompilerMessage( + name: "link", + kind: .signalled( + .init( + pid: 22699, + output: nil + ) + ) + ), + ], + errorDescription: nil + ) } @Test @@ -154,27 +192,37 @@ struct SwiftCompilerOutputParserTests { let delegate = MockSwiftCompilerOutputParserDelegate() let parser = SwiftCompilerOutputParser(targetName: "dummy", delegate: delegate) - parser.parse(bytes: """ - 2A - - """.utf8) - delegate.assert(messages: [ - SwiftCompilerMessage(name: "unknown", kind: .unparsableOutput("2A\n")) - ], errorDescription: nil) - - parser.parse(bytes: """ - 119 - { - "kind": "signalled", - "name": "link", - "pid": 22699, - "error-message": "Segmentation fault: 11", - "signal": 4 - } - """.utf8) - delegate.assert(messages: [ - SwiftCompilerMessage(name: "link", kind: .signalled(.init(pid: 22699, output: nil))) - ], errorDescription: nil) + parser.parse( + bytes: """ + 2A + + """.utf8 + ) + delegate.assert( + messages: [ + SwiftCompilerMessage(name: "unknown", kind: .unparsableOutput("2A\n")) + ], + errorDescription: nil + ) + + parser.parse( + bytes: """ + 119 + { + "kind": "signalled", + "name": "link", + "pid": 22699, + "error-message": "Segmentation fault: 11", + "signal": 4 + } + """.utf8 + ) + delegate.assert( + messages: [ + SwiftCompilerMessage(name: "link", kind: .signalled(.init(pid: 22699, output: nil))) + ], + errorDescription: nil + ) } @Test @@ -182,31 +230,38 @@ struct SwiftCompilerOutputParserTests { let delegate = MockSwiftCompilerOutputParserDelegate() let parser = SwiftCompilerOutputParser(targetName: "dummy", delegate: delegate) - parser.parse(bytes: """ - 119 - { - "kind": "signalled", - "name": "link", - "pid": 22699, - "error-message": "Segmentation fault: 11", - "signal": 4 - } - """.utf8) - delegate.assert(messages: [ - SwiftCompilerMessage(name: "link", kind: .signalled(.init(pid: 22699, output: nil))) - ], errorDescription: nil) - - parser.parse(bytes: """ - - 117 - { - "kind": "finished", - "name": "compile", - "pid": 22698, - "exit-status": 1, - "output": "error: it failed :-(" - } - """.utf8) + parser.parse( + bytes: """ + 119 + { + "kind": "signalled", + "name": "link", + "pid": 22699, + "error-message": "Segmentation fault: 11", + "signal": 4 + } + """.utf8 + ) + delegate.assert( + messages: [ + SwiftCompilerMessage(name: "link", kind: .signalled(.init(pid: 22699, output: nil))) + ], + errorDescription: nil + ) + + parser.parse( + bytes: """ + + 117 + { + "kind": "finished", + "name": "compile", + "pid": 22698, + "exit-status": 1, + "output": "error: it failed :-(" + } + """.utf8 + ) delegate.assert(messages: [], errorDescription: nil) } } diff --git a/Tests/BuildTests/WindowsBuildPlanTests.swift b/Tests/BuildTests/WindowsBuildPlanTests.swift index e5f3ea56a0a..6750a341b7f 100644 --- a/Tests/BuildTests/WindowsBuildPlanTests.swift +++ b/Tests/BuildTests/WindowsBuildPlanTests.swift @@ -18,8 +18,7 @@ import Basics import LLBuildManifest import _InternalTestSupport -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph struct WindowsBuildPlanTests { // Tests that our build plan is build correctly to handle separation @@ -67,13 +66,16 @@ struct WindowsBuildPlanTests { path: "/exePkg", dependencies: [.fileSystem(path: "/libPkg")], targets: [ - .init(name: "exe", dependencies: [ - .product(name: "DLLProduct", package: "libPkg"), - .product(name: "StaticProduct", package: "libPkg"), - .product(name: "ObjectProduct", package: "libPkg"), - ]), + .init( + name: "exe", + dependencies: [ + .product(name: "DLLProduct", package: "libPkg"), + .product(name: "StaticProduct", package: "libPkg"), + .product(name: "ObjectProduct", package: "libPkg"), + ] + ) ] - ) + ), ], observabilityScope: observability.topScope ) diff --git a/Tests/CommandsTests/APIDiffTests.swift b/Tests/CommandsTests/APIDiffTests.swift index 15cd185c307..572bd2506f3 100644 --- a/Tests/CommandsTests/APIDiffTests.swift +++ b/Tests/CommandsTests/APIDiffTests.swift @@ -15,8 +15,7 @@ import Build import Commands import SPMBuildCore -@_spi(SwiftPMInternal) -import DriverSupport +@_spi(SwiftPMInternal) import DriverSupport import Foundation import PackageModel @@ -134,8 +133,11 @@ struct APIDiffTests { string: "API breakage: class Qux has generic signature change from to \n" ) await expectThrowsCommandExecutionError( - try await execute(["diagnose-api-breaking-changes", "1.2.3", "--breakage-allowlist-path", customAllowlistPath.pathString], - packagePath: packageRoot, buildSystem: buildSystem) + try await execute( + ["diagnose-api-breaking-changes", "1.2.3", "--breakage-allowlist-path", customAllowlistPath.pathString], + packagePath: packageRoot, + buildSystem: buildSystem + ) ) { error in #expect(!error.stdout.contains("💔 API breakage: class Qux has generic signature change from to ")) #expect(error.stdout.contains("1 breaking change detected in Qux")) @@ -237,8 +239,11 @@ struct APIDiffTests { // Test diagnostics await expectThrowsCommandExecutionError( - try await execute(["diagnose-api-breaking-changes", "1.2.3", "--targets", "NotATarget", "Exec", "--products", "NotAProduct", "Exec"], - packagePath: packageRoot, buildSystem: buildSystem) + try await execute( + ["diagnose-api-breaking-changes", "1.2.3", "--targets", "NotATarget", "Exec", "--products", "NotAProduct", "Exec"], + packagePath: packageRoot, + buildSystem: buildSystem + ) ) { error in #expect(error.stderr.contains("error: no such product 'NotAProduct'")) #expect(error.stderr.contains("error: no such target 'NotATarget'")) @@ -260,15 +265,17 @@ struct APIDiffTests { try await fixture(name: "Miscellaneous/APIDiff/") { fixturePath in let packageRoot = fixturePath.appending("CTargetDep") // Overwrite the existing decl. - try localFileSystem.writeFileContents(packageRoot.appending(components: "Sources", "Bar", "Bar.swift"), string: - """ - import Foo - - public func bar() -> String { - foo() - return "hello, world!" - } - """ + try localFileSystem.writeFileContents( + packageRoot.appending(components: "Sources", "Bar", "Bar.swift"), + string: + """ + import Foo + + public func bar() -> String { + foo() + return "hello, world!" + } + """ ) await expectThrowsCommandExecutionError(try await execute(["diagnose-api-breaking-changes", "1.2.3"], packagePath: packageRoot, buildSystem: buildSystem)) { error in #expect(error.stdout.contains("1 breaking change detected in Bar")) @@ -344,24 +351,26 @@ struct APIDiffTests { packageRoot.appending(components: "Sources", "Foo", "Foo.swift"), string: #"public let foo = "All new module!""# ) - try localFileSystem.writeFileContents(packageRoot.appending("Package.swift"), string: - """ - // swift-tools-version:4.2 - import PackageDescription - - let package = Package( - name: "Bar", - products: [ - .library(name: "Baz", targets: ["Baz"]), - .library(name: "Qux", targets: ["Qux", "Foo"]), - ], - targets: [ - .target(name: "Baz"), - .target(name: "Qux"), - .target(name: "Foo") - ] - ) - """ + try localFileSystem.writeFileContents( + packageRoot.appending("Package.swift"), + string: + """ + // swift-tools-version:4.2 + import PackageDescription + + let package = Package( + name: "Bar", + products: [ + .library(name: "Baz", targets: ["Baz"]), + .library(name: "Qux", targets: ["Qux", "Foo"]), + ], + targets: [ + .target(name: "Baz"), + .target(name: "Qux"), + .target(name: "Foo") + ] + ) + """ ) let (output, _) = try await execute(["diagnose-api-breaking-changes", "1.2.3"], packagePath: packageRoot, buildSystem: buildSystem) #expect(output.contains("No breaking changes detected in Baz")) @@ -407,9 +416,11 @@ struct APIDiffTests { try repo.stage(file: "Foo.swift") try repo.commit(message: "Add foo") await expectThrowsCommandExecutionError( - try await execute(["diagnose-api-breaking-changes", "main", "--baseline-dir", baselineDir.pathString], - packagePath: packageRoot, - buildSystem: buildSystem) + try await execute( + ["diagnose-api-breaking-changes", "main", "--baseline-dir", baselineDir.pathString], + packagePath: packageRoot, + buildSystem: buildSystem + ) ) { error in #expect(error.stdout.contains("1 breaking change detected in Foo")) #expect(error.stdout.contains("💔 API breakage: func foo() has been removed")) @@ -424,9 +435,11 @@ struct APIDiffTests { try repo.stage(file: "Foo.swift") try repo.commit(message: "Add foo") try repo.checkout(revision: .init(identifier: "feature")) - let (output, _) = try await execute(["diagnose-api-breaking-changes", "main", "--baseline-dir", baselineDir.pathString], - packagePath: packageRoot, - buildSystem: buildSystem) + let (output, _) = try await execute( + ["diagnose-api-breaking-changes", "main", "--baseline-dir", baselineDir.pathString], + packagePath: packageRoot, + buildSystem: buildSystem + ) #expect(output.contains("No breaking changes detected in Foo")) } } @@ -485,10 +498,14 @@ struct APIDiffTests { var initialTimestamp: Date? try await expectThrowsCommandExecutionError( - try await execute(["diagnose-api-breaking-changes", "1.2.3", - "--baseline-dir", baselineDir.pathString], - packagePath: packageRoot, - buildSystem: buildSystem) + try await execute( + [ + "diagnose-api-breaking-changes", "1.2.3", + "--baseline-dir", baselineDir.pathString, + ], + packagePath: packageRoot, + buildSystem: buildSystem + ) ) { error in #expect(error.stdout.contains("1 breaking change detected in Foo")) #expect(error.stdout.contains("💔 API breakage: func foo() has been removed")) @@ -500,10 +517,14 @@ struct APIDiffTests { try await Task.sleep(for: .seconds(1)) try await expectThrowsCommandExecutionError( - try await execute(["diagnose-api-breaking-changes", "1.2.3", - "--baseline-dir", baselineDir.pathString], - packagePath: packageRoot, - buildSystem: buildSystem) + try await execute( + [ + "diagnose-api-breaking-changes", "1.2.3", + "--baseline-dir", baselineDir.pathString, + ], + packagePath: packageRoot, + buildSystem: buildSystem + ) ) { error in #expect(error.stdout.contains("1 breaking change detected in Foo")) #expect(error.stdout.contains("💔 API breakage: func foo() has been removed")) @@ -515,10 +536,14 @@ struct APIDiffTests { try await Task.sleep(for: .seconds(1)) await expectThrowsCommandExecutionError( - try await execute(["diagnose-api-breaking-changes", "1.2.3", - "--baseline-dir", baselineDir.pathString, "--regenerate-baseline"], - packagePath: packageRoot, - buildSystem: buildSystem) + try await execute( + [ + "diagnose-api-breaking-changes", "1.2.3", + "--baseline-dir", baselineDir.pathString, "--regenerate-baseline", + ], + packagePath: packageRoot, + buildSystem: buildSystem + ) ) { error in #expect(error.stdout.contains("1 breaking change detected in Foo")) #expect(error.stdout.contains("💔 API breakage: func foo() has been removed")) diff --git a/Tests/CommandsTests/BuildCommandTests.swift b/Tests/CommandsTests/BuildCommandTests.swift index 35eca4d2c1d..4856fc49640 100644 --- a/Tests/CommandsTests/BuildCommandTests.swift +++ b/Tests/CommandsTests/BuildCommandTests.swift @@ -60,7 +60,7 @@ fileprivate func build( buildSystem: BuildSystemProvider.Kind, ) async throws -> BuildResult { do { - let (stdout, stderr) = try await execute(args, packagePath: packagePath,configuration: configuration, buildSystem: buildSystem,) + let (stdout, stderr) = try await execute(args, packagePath: packagePath, configuration: configuration, buildSystem: buildSystem, ) defer { } let (binPathOutput, _) = try await execute( @@ -82,16 +82,16 @@ fileprivate func build( if buildSystem == .native { moduleContents = (try? localFileSystem.getDirectoryContents(binPath.appending(component: "Modules"))) ?? [] } else { - let moduleDirs = (try? localFileSystem.getDirectoryContents(binPath).filter { - $0.hasSuffix(".swiftmodule") - }) ?? [] + let moduleDirs = + (try? localFileSystem.getDirectoryContents(binPath).filter { + $0.hasSuffix(".swiftmodule") + }) ?? [] for dir: String in moduleDirs { moduleContents += (try? localFileSystem.getDirectoryContents(binPath.appending(component: dir)).map { "\(dir)/\($0)" }) ?? [] } } - if cleanAfterward { try await executeSwiftPackage( packagePath, @@ -127,7 +127,6 @@ fileprivate func build( ) struct BuildCommandTestCases { - @Test( buildDataUsingAllBuildSystemWithTags.tags, arguments: buildDataUsingAllBuildSystemWithTags.buildData, @@ -225,7 +224,6 @@ struct BuildCommandTestCases { #expect(stdout.contains(expectedRegex)) } - @Test( .tags( .Feature.CommandLineArguments.ExplicitTargetDependencyImportCheck, @@ -241,7 +239,7 @@ struct BuildCommandTestCases { try await withKnownIssue("SWBINTTODO: Test fails because the warning message regarding missing imports is expected to be more verbose and actionable at the SwiftPM level with mention of the involved targets. This needs to be investigated. See case targetDiagnostic(TargetDiagnosticInfo) as a message type that may help.") { try await fixture(name: "Miscellaneous/ImportOfMissingDependency") { path in let fullPath = try resolveSymlinks(path) - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await build( ["--explicit-target-dependency-import-check=warn"], packagePath: fullPath, @@ -279,7 +277,7 @@ struct BuildCommandTestCases { try await withKnownIssue("SWBINTTODO: Test fails because the warning message regarding missing imports is expected to be more verbose and actionable at the SwiftPM level with mention of the involved targets. This needs to be investigated. See case targetDiagnostic(TargetDiagnosticInfo) as a message type that may help.") { try await fixture(name: "Miscellaneous/ImportOfMissingDependency") { path in let fullPath = try resolveSymlinks(path) - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await build( ["--explicit-target-dependency-import-check=error"], packagePath: fullPath, @@ -311,7 +309,7 @@ struct BuildCommandTestCases { ) async throws { try await fixture(name: "Miscellaneous/ImportOfMissingDependency") { path in let fullPath = try resolveSymlinks(path) - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await build( [], packagePath: fullPath, @@ -355,8 +353,8 @@ struct BuildCommandTestCases { @Test( .tags( - .Feature.Command.Build, - .Feature.TargetType.Executable + .Feature.Command.Build, + .Feature.TargetType.Executable ), .IssueWindowsLongPath, buildDataUsingAllBuildSystemWithTags.tags, @@ -407,19 +405,19 @@ struct BuildCommandTestCases { buildSystem: buildSystem, ) switch buildSystem { - case .native, .swiftbuild: - withKnownIssue("Found multiple targets named 'lib1'") { - #expect( - stderr.contains( - "'--product' cannot be used with the automatic product 'lib1'; building the default target instead" - ) + case .native, .swiftbuild: + withKnownIssue("Found multiple targets named 'lib1'") { + #expect( + stderr.contains( + "'--product' cannot be used with the automatic product 'lib1'; building the default target instead" ) - } when: { - .swiftbuild == buildSystem - } - case .xcode: - // Do nothing. - break + ) + } when: { + .swiftbuild == buildSystem + } + case .xcode: + // Do nothing. + break } } } when: { @@ -472,7 +470,7 @@ struct BuildCommandTestCases { buildData: BuildData, ) async throws { try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await execute( ["--product", "exec1", "--target", "exec2"], packagePath: fixturePath, @@ -501,7 +499,7 @@ struct BuildCommandTestCases { buildData: BuildData, ) async throws { try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await execute( ["--product", "exec1", "--build-tests"], packagePath: fixturePath, @@ -530,7 +528,7 @@ struct BuildCommandTestCases { data: BuildData, ) async throws { try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await execute( ["--build-tests", "--target", "exec2"], packagePath: fixturePath, @@ -560,7 +558,7 @@ struct BuildCommandTestCases { data: BuildData, ) async throws { try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await execute( ["--build-tests", "--target", "exec2", "--product", "exec1"], packagePath: fixturePath, @@ -576,11 +574,9 @@ struct BuildCommandTestCases { withKnownIssue(isIntermittent: true) { #expect(stderr.contains("error: '--product', '--target', and '--build-tests' are mutually exclusive"), "stout: \(stdout)") } when: { - ( - ProcessInfo.hostOperatingSystem == .windows && ( - data.buildSystem == .native - || (data.buildSystem == .swiftbuild && data.config == .debug) - )) + (ProcessInfo.hostOperatingSystem == .windows + && (data.buildSystem == .native + || (data.buildSystem == .swiftbuild && data.config == .debug))) } } } @@ -597,7 +593,7 @@ struct BuildCommandTestCases { ) async throws { try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in let productName = "UnknownProduct" - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await execute( ["--product", productName], packagePath: fixturePath, @@ -612,14 +608,14 @@ struct BuildCommandTestCases { } switch data.buildSystem { - case .native: - #expect(stderr.contains("error: no product named '\(productName)'")) - case .swiftbuild, .xcode: - let expectedErrorMessageRegex = try Regex("error: Could not find target named '\(productName).*'") - #expect( - stderr.contains(expectedErrorMessageRegex), - "expect log not emitted.\nstdout: '\(stdout)'\n\nstderr: '\(stderr)'", - ) + case .native: + #expect(stderr.contains("error: no product named '\(productName)'")) + case .swiftbuild, .xcode: + let expectedErrorMessageRegex = try Regex("error: Could not find target named '\(productName).*'") + #expect( + stderr.contains(expectedErrorMessageRegex), + "expect log not emitted.\nstdout: '\(stdout)'\n\nstderr: '\(stderr)'", + ) } } } @@ -637,7 +633,7 @@ struct BuildCommandTestCases { try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in let buildSystem = data.buildSystem let targetName = "UnknownTargetName" - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await execute( ["--target", targetName], packagePath: fixturePath, @@ -652,10 +648,10 @@ struct BuildCommandTestCases { } let expectedErrorMessage: String switch buildSystem { - case .native: - expectedErrorMessage = "error: no target named '\(targetName)'" - case .swiftbuild, .xcode: - expectedErrorMessage = "error: Could not find target named '\(targetName)'" + case .native: + expectedErrorMessage = "error: no target named '\(targetName)'" + case .swiftbuild, .xcode: + expectedErrorMessage = "error: Could not find target named '\(targetName)'" } #expect( stderr.contains(expectedErrorMessage), @@ -669,7 +665,8 @@ struct BuildCommandTestCases { .Feature.CommandLineArguments.Product, ), buildDataUsingAllBuildSystemWithTags.tags, - arguments: buildDataUsingAllBuildSystemWithTags.buildData, ["ClangExecSingleFile", "SwiftExecSingleFile", "SwiftExecMultiFile"], + arguments: buildDataUsingAllBuildSystemWithTags.buildData, + ["ClangExecSingleFile", "SwiftExecSingleFile", "SwiftExecMultiFile"], ) func atMainSupport( data: BuildData, @@ -692,7 +689,7 @@ struct BuildCommandTestCases { #expect(result.binContents.contains(executableName(executable))) } } when: { - ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild + ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild } } @@ -750,7 +747,7 @@ struct BuildCommandTestCases { // FIXME: We create the modulemap during build planning, hence this ugliness. let bTargetBuildDir = - ((try? localFileSystem.getDirectoryContents(result.binPath.appending("BTarget1.build"))) ?? []) + ((try? localFileSystem.getDirectoryContents(result.binPath.appending("BTarget1.build"))) ?? []) .filter { $0 != moduleMapFilename } #expect(bTargetBuildDir.isEmpty, "bTargetBuildDir should be empty") @@ -790,14 +787,14 @@ struct BuildCommandTestCases { buildSystem: buildSystem, ) switch buildSystem { - case .native: - #expect(result.moduleContents.contains("A.swiftinterface")) - #expect(result.moduleContents.contains("B.swiftinterface")) - case .swiftbuild, .xcode: - let moduleARegex = try Regex(#"A[.]swiftmodule[/].*[.]swiftinterface"#) - let moduleBRegex = try Regex(#"B[.]swiftmodule[/].*[.]swiftmodule"#) - #expect(result.moduleContents.contains { $0.contains(moduleARegex) }) - #expect(result.moduleContents.contains { $0.contains(moduleBRegex) }) + case .native: + #expect(result.moduleContents.contains("A.swiftinterface")) + #expect(result.moduleContents.contains("B.swiftinterface")) + case .swiftbuild, .xcode: + let moduleARegex = try Regex(#"A[.]swiftmodule[/].*[.]swiftinterface"#) + let moduleBRegex = try Regex(#"B[.]swiftmodule[/].*[.]swiftmodule"#) + #expect(result.moduleContents.contains { $0.contains(moduleARegex) }) + #expect(result.moduleContents.contains { $0.contains(moduleBRegex) }) } } when: { // errors with SwiftBuild on Windows possibly due to long path on windows only for swift build @@ -827,18 +824,18 @@ struct BuildCommandTestCases { buildSystem: buildSystem, ) switch buildSystem { - case .native: - #expect(result.moduleContents.contains("A.swiftinterface")) - #expect(result.moduleContents.contains("B.swiftinterface")) - case .swiftbuild, .xcode: - let moduleARegex = try Regex(#"A[.]swiftmodule[/].*[.]swiftinterface"#) - let moduleBRegex = try Regex(#"B[.]swiftmodule[/].*[.]swiftmodule"#) - withKnownIssue("SWBINTTODO: Test failed because of missing 'A.swiftmodule/*.swiftinterface' files") { - #expect(result.moduleContents.contains { $0.contains(moduleARegex) }) - } when: { - buildSystem == .swiftbuild - } - #expect(result.moduleContents.contains { $0.contains(moduleBRegex) }) + case .native: + #expect(result.moduleContents.contains("A.swiftinterface")) + #expect(result.moduleContents.contains("B.swiftinterface")) + case .swiftbuild, .xcode: + let moduleARegex = try Regex(#"A[.]swiftmodule[/].*[.]swiftinterface"#) + let moduleBRegex = try Regex(#"B[.]swiftmodule[/].*[.]swiftmodule"#) + withKnownIssue("SWBINTTODO: Test failed because of missing 'A.swiftmodule/*.swiftinterface' files") { + #expect(result.moduleContents.contains { $0.contains(moduleARegex) }) + } when: { + buildSystem == .swiftbuild + } + #expect(result.moduleContents.contains { $0.contains(moduleBRegex) }) } } } when: { @@ -906,29 +903,29 @@ struct BuildCommandTestCases { arguments: buildDataUsingAllBuildSystemWithTags.buildData, ) func buildStartMessage( - data: BuildData, + data: BuildData, ) async throws { let buildSystem = data.buildSystem - let configuration = data.config + let configuration = data.config try await fixture(name: "DependencyResolution/Internal/Simple") { fixturePath in let result = try await execute([], packagePath: fixturePath, configuration: configuration, buildSystem: buildSystem, throwIfCommandFails: false) let expectedString: String switch configuration { - case .debug: - expectedString = "debugging" - case .release: - expectedString = "production" + case .debug: + expectedString = "debugging" + case .release: + expectedString = "production" } switch buildSystem { - case .native, .swiftbuild: - #expect( - result.stdout.contains("Building for \(expectedString)"), - "expect log not emitted. got stdout: '\(result.stdout)'\n\nstderr '\(result.stderr)'", - ) - case .xcode: - // Xcode build system does not emit the build started message. - break + case .native, .swiftbuild: + #expect( + result.stdout.contains("Building for \(expectedString)"), + "expect log not emitted. got stdout: '\(result.stdout)'\n\nstderr '\(result.stderr)'", + ) + case .xcode: + // Xcode build system does not emit the build started message. + break } } } @@ -946,27 +943,27 @@ struct BuildCommandTestCases { try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in // try await building using XCBuild with default parameters. This should succeed. We build verbosely so we get // full command lines. - let output: (stdout: String, stderr: String) = try await execute( - ["-v"], - packagePath: fixturePath, - configuration: data.config, - buildSystem: buildSystem, - ) + let output: (stdout: String, stderr: String) = try await execute( + ["-v"], + packagePath: fixturePath, + configuration: data.config, + buildSystem: buildSystem, + ) // In the case of the native build system check for the cross-compile target, only for macOS - #if os(macOS) - if buildSystem == .native { - let targetTripleString = try UserToolchain.default.targetTriple.tripleString(forPlatformVersion: "") - #expect(output.stdout.contains("-target \(targetTripleString)")) - } - #endif + #if os(macOS) + if buildSystem == .native { + let targetTripleString = try UserToolchain.default.targetTriple.tripleString(forPlatformVersion: "") + #expect(output.stdout.contains("-target \(targetTripleString)")) + } + #endif // Look for build completion message from the particular build system #expect(output.stdout.contains("Build complete!")) } } when: { (buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows) - || (buildSystem == .native && data.config == .release && ProcessInfo.hostOperatingSystem == .windows) + || (buildSystem == .native && data.config == .release && ProcessInfo.hostOperatingSystem == .windows) } } @@ -1032,40 +1029,40 @@ struct BuildCommandTestCases { let buildSystem = data.buildSystem let config = data.config try await withKnownIssue(isIntermittent: true) { - try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in - let swiftCompilerPath = try UserToolchain.default.swiftCompilerPath - // try await building without specifying overrides. This should succeed, and should use the default - // compiler path. - let defaultOutput = try await execute( - ["--vv"], - packagePath: fixturePath, - configuration: config, - buildSystem: buildSystem, - ).stdout - #expect(defaultOutput.contains(swiftCompilerPath.pathString)) - - // Now try await building while specifying a faulty compiler override. This should fail. Note that - // we need to set the executable to use for the manifest itself to the default one, since it defaults to - // SWIFT_EXEC if not provided. - let error = await #expect(throws: SwiftPMError.self ) { - try await execute( + try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in + let swiftCompilerPath = try UserToolchain.default.swiftCompilerPath + // try await building without specifying overrides. This should succeed, and should use the default + // compiler path. + let defaultOutput = try await execute( ["--vv"], - environment: [ - "SWIFT_EXEC": "/usr/bin/false", - "SWIFT_EXEC_MANIFEST": swiftCompilerPath.pathString, - ], packagePath: fixturePath, configuration: config, buildSystem: buildSystem, - ) - } - // THEN I expect a failure - guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { - Issue.record("Incorrect error was raised.") - return + ).stdout + #expect(defaultOutput.contains(swiftCompilerPath.pathString)) + + // Now try await building while specifying a faulty compiler override. This should fail. Note that + // we need to set the executable to use for the manifest itself to the default one, since it defaults to + // SWIFT_EXEC if not provided. + let error = await #expect(throws: SwiftPMError.self) { + try await execute( + ["--vv"], + environment: [ + "SWIFT_EXEC": "/usr/bin/false", + "SWIFT_EXEC_MANIFEST": swiftCompilerPath.pathString, + ], + packagePath: fixturePath, + configuration: config, + buildSystem: buildSystem, + ) + } + // THEN I expect a failure + guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return + } + #expect(stderr.contains("/usr/bin/false")) } - #expect(stderr.contains("/usr/bin/false")) - } } when: { buildSystem == .swiftbuild } @@ -1114,10 +1111,10 @@ struct BuildCommandTestCases { buildSystem: buildSystem, ).stdout switch buildSystem { - case .native, .xcode: - #expect(!output.hasPrefix("digraph PIF {")) - case .swiftbuild: - #expect(output.hasPrefix("digraph PIF {")) + case .native, .xcode: + #expect(!output.hasPrefix("digraph PIF {")) + case .swiftbuild: + #expect(output.hasPrefix("digraph PIF {")) } } } @@ -1135,7 +1132,7 @@ struct BuildCommandTestCases { func swiftDriverRawOutputGetsNewlines( buildSystem: BuildSystemProvider.Kind, ) async throws { - try await withKnownIssue( + try await withKnownIssue( "error produced for this fixture", isIntermittent: ProcessInfo.hostOperatingSystem == .linux, ) { @@ -1200,7 +1197,7 @@ struct BuildCommandTestCases { try await withKnownIssue( "https://github.com/swiftlang/swift-package-manager/issues/8659, SWIFT_EXEC override is not working", isIntermittent: (buildSystem == .native && config == .release) - ){ + ) { // Build with a swiftc that returns version 1.0, we expect a successful build which compiles our one source // file. do { @@ -1273,8 +1270,8 @@ struct BuildCommandTestCases { } } when: { (ProcessInfo.hostOperatingSystem == .windows) - || ([.xcode, .swiftbuild].contains(buildSystem)) - || (buildSystem == .native && config == .release) + || ([.xcode, .swiftbuild].contains(buildSystem)) + || (buildSystem == .native && config == .release) } } } @@ -1296,84 +1293,84 @@ struct BuildCommandTestCases { ) async throws { try await withKnownIssue(isIntermittent: (ProcessInfo.hostOperatingSystem == .linux)) { try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in - #if os(macOS) - // try await building with default parameters. This should succeed. We build verbosely so we get full command - // lines. - var buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .debug, buildSystem: buildSystem,) + #if os(macOS) + // try await building with default parameters. This should succeed. We build verbosely so we get full command + // lines. + var buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .debug, buildSystem: buildSystem, ) - // TODO verification of the ad-hoc code signing can be done by `swift run` of the executable in these cases once swiftbuild build system is working with that - #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) + // TODO verification of the ad-hoc code signing can be done by `swift run` of the executable in these cases once swiftbuild build system is working with that + #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) - buildResult = try await build(["-v"], packagePath: fixturePath, configuration:.debug, buildSystem: buildSystem,) + buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .debug, buildSystem: buildSystem, ) - #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) - // Build with different combinations of the entitlement flag and debug/release build configurations. + // Build with different combinations of the entitlement flag and debug/release build configurations. - buildResult = try await build( - ["--enable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - configuration: .release, - buildSystem: buildSystem, - ) + buildResult = try await build( + ["--enable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .release, + buildSystem: buildSystem, + ) - #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) - buildResult = try await build( - ["--enable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - configuration: .debug, - buildSystem: buildSystem, - ) + buildResult = try await build( + ["--enable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .debug, + buildSystem: buildSystem, + ) - #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) - buildResult = try await build( - ["--disable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - configuration: .debug, - buildSystem: buildSystem, - ) + buildResult = try await build( + ["--disable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .debug, + buildSystem: buildSystem, + ) - #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) - buildResult = try await build( - ["--disable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - configuration: .release, - buildSystem: buildSystem, - ) + buildResult = try await build( + ["--disable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .release, + buildSystem: buildSystem, + ) - #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) - #else - var buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .debug, buildSystem: buildSystem,) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #else + var buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .debug, buildSystem: buildSystem, ) - #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) - buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .release,buildSystem: buildSystem,) + buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .release, buildSystem: buildSystem, ) - #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) - buildResult = try await build( - ["--disable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - configuration: .release, - buildSystem: buildSystem, - ) + buildResult = try await build( + ["--disable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .release, + buildSystem: buildSystem, + ) - #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) - #expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning)) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning)) - buildResult = try await build( - ["--enable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - configuration: .release, - buildSystem: buildSystem, - ) + buildResult = try await build( + ["--enable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .release, + buildSystem: buildSystem, + ) - #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) - #expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning)) - #endif + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning)) + #endif buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .release, buildSystem: buildSystem) @@ -1411,14 +1408,14 @@ struct BuildCommandTestCases { let testBinaryPath = buildResult.binPath.appending("IgnoresLinuxMainPackageTests.xctest") switch buildSystem { - case .native: - expectFileExists(at: testBinaryPath) - _ = try await AsyncProcess.checkNonZeroExit(arguments: [testBinaryPath.pathString]) - case .swiftbuild: - // there are no additional check - break - case .xcode: - Issue.record("Test expectations have not been implemented.") + case .native: + expectFileExists(at: testBinaryPath) + _ = try await AsyncProcess.checkNonZeroExit(arguments: [testBinaryPath.pathString]) + case .swiftbuild: + // there are no additional check + break + case .xcode: + Issue.record("Test expectations have not been implemented.") } } } @@ -1431,7 +1428,8 @@ struct BuildCommandTestCases { .Feature.CommandLineArguments.Xswiftc, ), buildDataUsingAllBuildSystemWithTags.tags, - arguments: buildDataUsingAllBuildSystemWithTags.buildData,[ + arguments: buildDataUsingAllBuildSystemWithTags.buildData, + [ ["--verbose"], ["--very-verbose"], ["-Xswiftc", "-diagnostic-style=llvm"], @@ -1449,19 +1447,23 @@ struct BuildCommandTestCases { let base = try RelativePath(validating: ".build") let path = try base.appending(components: buildSystem.binPath(for: configuration, scratchPath: [])) switch buildSystem { - case .xcode: - return triple.platformName() == "macosx" ? path.appending("ExecutableNew") : path - .appending("ExecutableNew.swiftmodule") - .appending("Project") - .appending("\(triple).swiftsourceinfo") - case .swiftbuild: - return triple.platformName() == "macosx" ? path.appending("ExecutableNew") : path - .appending("ExecutableNew.swiftmodule") - .appending("Project") - .appending("\(triple).swiftsourceinfo") - case .native: - return path.appending("ExecutableNew.build") - .appending("main.swift.o") + case .xcode: + return triple.platformName() == "macosx" + ? path.appending("ExecutableNew") + : path + .appending("ExecutableNew.swiftmodule") + .appending("Project") + .appending("\(triple).swiftsourceinfo") + case .swiftbuild: + return triple.platformName() == "macosx" + ? path.appending("ExecutableNew") + : path + .appending("ExecutableNew.swiftmodule") + .appending("Project") + .appending("\(triple).swiftsourceinfo") + case .native: + return path.appending("ExecutableNew.build") + .appending("main.swift.o") } } @@ -1469,8 +1471,9 @@ struct BuildCommandTestCases { """ Windows: Sometimes failed to build due to a possible path issue All: --very-verbose causes rebuild on SwiftBuild (https://github.com/swiftlang/swift-package-manager/issues/9299) - """, - isIntermittent: true) { + """, + isIntermittent: true + ) { try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in _ = try await build( [], @@ -1495,7 +1498,7 @@ struct BuildCommandTestCases { } } when: { data.buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows - || (data.buildSystem == .swiftbuild && flags.contains("--very-verbose")) + || (data.buildSystem == .swiftbuild && flags.contains("--very-verbose")) } } @@ -1503,12 +1506,12 @@ struct BuildCommandTestCases { buildDataUsingBuildSystemAvailableOnAllPlatformsWithTags.tags, arguments: buildDataUsingBuildSystemAvailableOnAllPlatformsWithTags.buildData, ) - func parseAsLibraryCriteria( + func parseAsLibraryCriteria( buildData: BuildData, ) async throws { try await withKnownIssue { try await fixture(name: "Miscellaneous/ParseAsLibrary") { fixturePath in - _ = try await executeSwiftBuild( + _ = try await executeSwiftBuild( fixturePath, configuration: buildData.config, buildSystem: buildData.buildSystem, @@ -1516,8 +1519,7 @@ struct BuildCommandTestCases { ) } } when: { - ProcessInfo.hostOperatingSystem == .windows && - buildData.buildSystem == .swiftbuild + ProcessInfo.hostOperatingSystem == .windows && buildData.buildSystem == .swiftbuild } } @@ -1534,7 +1536,7 @@ struct BuildCommandTestCases { let expected = 0 try await fixture(name: "Miscellaneous/Errors/FatalErrorInSingleXCTest/TypeLibrary") { fixturePath in // WHEN swift-build --build-tests is executed" - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await execute( ["--build-tests"], packagePath: fixturePath, @@ -1566,14 +1568,14 @@ struct BuildCommandTestCases { buildDataUsingAllBuildSystemWithTags.tags, arguments: buildDataUsingAllBuildSystemWithTags.buildData, ) - func swiftBuildQuietLogLevel( + func swiftBuildQuietLogLevel( data: BuildData, - ) async throws { - let buildSystem = data.buildSystem - let configuration = data.config - try await withKnownIssue { - // GIVEN we have a simple test package - try await fixture(name: "Miscellaneous/SwiftBuild") { fixturePath in + ) async throws { + let buildSystem = data.buildSystem + let configuration = data.config + try await withKnownIssue { + // GIVEN we have a simple test package + try await fixture(name: "Miscellaneous/SwiftBuild") { fixturePath in //WHEN we build with the --quiet option let (stdout, stderr) = try await executeSwiftBuild( fixturePath, @@ -1582,14 +1584,13 @@ struct BuildCommandTestCases { buildSystem: buildSystem ) // THEN we should not see any output in stderr - #expect(stderr.isEmpty) + #expect(stderr.isEmpty) // AND no content in stdout - #expect(stdout.isEmpty) + #expect(stdout.isEmpty) } - } when: { - ProcessInfo.hostOperatingSystem == .windows && - buildSystem == .swiftbuild - } + } when: { + ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild + } } @Test( @@ -1600,29 +1601,29 @@ struct BuildCommandTestCases { buildDataUsingAllBuildSystemWithTags.tags, arguments: buildDataUsingAllBuildSystemWithTags.buildData, ) - func swiftBuildQuietLogLevelWithError( + func swiftBuildQuietLogLevelWithError( buildData: BuildData, ) async throws { let buildSystem = buildData.buildSystem let configuration = buildData.config - // GIVEN we have a simple test package + // GIVEN we have a simple test package try await fixture(name: "Miscellaneous/SwiftBuild") { fixturePath in let mainFilePath = fixturePath.appending("main.swift") try localFileSystem.removeFileTree(mainFilePath) try localFileSystem.writeFileContents( - mainFilePath, - string: """ - print("done" - """ + mainFilePath, + string: """ + print("done" + """ ) //WHEN we build with the --quiet option let error = await #expect(throws: SwiftPMError.self) { try await executeSwiftBuild( - fixturePath, - configuration: configuration, - extraArgs: ["--quiet"], - buildSystem: buildSystem + fixturePath, + configuration: configuration, + extraArgs: ["--quiet"], + buildSystem: buildSystem ) } @@ -1632,16 +1633,16 @@ struct BuildCommandTestCases { } switch buildSystem { - case .swiftbuild: - // THEN we should see output in stderr - #expect(stderr.isEmpty == false) - // AND no content in stdout - #expect(stdout.isEmpty) - case .native, .xcode: - // THEN we should see content in stdout - #expect(stdout.isEmpty == false) - // AND no output in stderr - #expect(stderr.isEmpty) + case .swiftbuild: + // THEN we should see output in stderr + #expect(stderr.isEmpty == false) + // AND no content in stdout + #expect(stdout.isEmpty) + case .native, .xcode: + // THEN we should see content in stdout + #expect(stdout.isEmpty == false) + // AND no output in stderr + #expect(stderr.isEmpty) } } } @@ -1665,43 +1666,43 @@ struct BuildCommandTestCases { // No triple - build should pass try await fixture(name: "Miscellaneous/RequiresOlderDeploymentTarget") { path in - try await executeSwiftBuild( - path, - configuration: configuration, - buildSystem: buildSystem, - throwIfCommandFails: true - ) + try await executeSwiftBuild( + path, + configuration: configuration, + buildSystem: buildSystem, + throwIfCommandFails: true + ) } let hostArch: String #if arch(arm64) - hostArch = "arm64" + hostArch = "arm64" #elseif arch(x86_64) - hostArch = "x86_64" + hostArch = "x86_64" #else - Issue.record("test is not supported on host arch") - return + Issue.record("test is not supported on host arch") + return #endif // Unversioned triple - build should pass try await fixture(name: "Miscellaneous/RequiresOlderDeploymentTarget") { path in - try await executeSwiftBuild( - path, - configuration: configuration, - extraArgs: ["--triple", "\(hostArch)-apple-macosx"], - buildSystem: buildSystem, - throwIfCommandFails: true - ) + try await executeSwiftBuild( + path, + configuration: configuration, + extraArgs: ["--triple", "\(hostArch)-apple-macosx"], + buildSystem: buildSystem, + throwIfCommandFails: true + ) } // Versioned triple with supported deployment target - build should pass try await fixture(name: "Miscellaneous/RequiresOlderDeploymentTarget") { path in - try await executeSwiftBuild( - path, - extraArgs: ["--triple", "\(hostArch)-apple-macosx12.0"], - buildSystem: buildSystem, - throwIfCommandFails: true - ) + try await executeSwiftBuild( + path, + extraArgs: ["--triple", "\(hostArch)-apple-macosx12.0"], + buildSystem: buildSystem, + throwIfCommandFails: true + ) } // Versioned triple with unsupported deployment target - build should fail @@ -1722,7 +1723,6 @@ struct BuildCommandTestCases { } } - @Test( .requireHostOS(.macOS), .tags( @@ -1811,6 +1811,3 @@ extension Triple { } } } - - - diff --git a/Tests/CommandsTests/CoverageTests.swift b/Tests/CommandsTests/CoverageTests.swift index 4872691725e..6a91934f96a 100644 --- a/Tests/CommandsTests/CoverageTests.swift +++ b/Tests/CommandsTests/CoverageTests.swift @@ -49,7 +49,7 @@ struct CoverageTests { extraArgs: ["--build-tests"], buildSystem: buildSystem, ) - await #expect(throws: (any Error).self ) { + await #expect(throws: (any Error).self) { try await executeSwiftTest( path, configuration: config, @@ -82,49 +82,49 @@ struct CoverageTests { let config = BuildConfiguration.debug // Test that enabling code coverage during building produces the expected folder. try await withKnownIssue(isIntermittent: true) { - try await fixture(name: "Miscellaneous/TestDiscovery/Simple") { path in - let codeCovPathString = try await executeSwiftTest( - path, - configuration: config, - extraArgs: [ - "--show-coverage-path", - ], - throwIfCommandFails: true, - buildSystem: buildSystem, - ).stdout.trimmingCharacters(in: .whitespacesAndNewlines) - - let codeCovPath = try AbsolutePath(validating: codeCovPathString) - - // WHEN we build with coverage enabled - try await withKnownIssue { - try await executeSwiftBuild( - path, - configuration: config, - extraArgs: ["--build-tests", "--enable-code-coverage"], - buildSystem: buildSystem, - ) - - // AND we test with coverag enabled and skip the build - try await executeSwiftTest( + try await fixture(name: "Miscellaneous/TestDiscovery/Simple") { path in + let codeCovPathString = try await executeSwiftTest( path, configuration: config, extraArgs: [ - "--skip-build", - "--enable-code-coverage", + "--show-coverage-path" ], + throwIfCommandFails: true, buildSystem: buildSystem, - ) + ).stdout.trimmingCharacters(in: .whitespacesAndNewlines) - // THEN we expect the file to exists - expectFileExists(at: codeCovPath) + let codeCovPath = try AbsolutePath(validating: codeCovPathString) - // AND the parent directory is non empty - let codeCovFiles = try localFileSystem.getDirectoryContents(codeCovPath.parentDirectory) - #expect(codeCovFiles.count > 0) - } when: { - ProcessInfo.hostOperatingSystem == .linux && buildSystem == .swiftbuild + // WHEN we build with coverage enabled + try await withKnownIssue { + try await executeSwiftBuild( + path, + configuration: config, + extraArgs: ["--build-tests", "--enable-code-coverage"], + buildSystem: buildSystem, + ) + + // AND we test with coverag enabled and skip the build + try await executeSwiftTest( + path, + configuration: config, + extraArgs: [ + "--skip-build", + "--enable-code-coverage", + ], + buildSystem: buildSystem, + ) + + // THEN we expect the file to exists + expectFileExists(at: codeCovPath) + + // AND the parent directory is non empty + let codeCovFiles = try localFileSystem.getDirectoryContents(codeCovPath.parentDirectory) + #expect(codeCovFiles.count > 0) + } when: { + ProcessInfo.hostOperatingSystem == .linux && buildSystem == .swiftbuild + } } - } } when: { ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild } @@ -134,7 +134,8 @@ struct CoverageTests { .tags( .Feature.Command.Test, ), - arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), [ + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + [ "Coverage/Simple", "Miscellaneous/TestDiscovery/Simple", ], @@ -148,7 +149,7 @@ struct CoverageTests { path, configuration: buildData.config, extraArgs: [ - "--show-coverage-path", + "--show-coverage-path" ], throwIfCommandFails: true, buildSystem: buildData.buildSystem, @@ -162,7 +163,7 @@ struct CoverageTests { path, configuration: buildData.config, extraArgs: [ - "--enable-code-coverage", + "--enable-code-coverage" ], throwIfCommandFails: true, buildSystem: buildData.buildSystem, diff --git a/Tests/CommandsTests/MermaidPackageSerializerTests.swift b/Tests/CommandsTests/MermaidPackageSerializerTests.swift index dc298245e3e..ba60b4a285e 100644 --- a/Tests/CommandsTests/MermaidPackageSerializerTests.swift +++ b/Tests/CommandsTests/MermaidPackageSerializerTests.swift @@ -14,16 +14,14 @@ import Foundation import class Basics.InMemoryFileSystem import class Basics.ObservabilitySystem -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import func PackageGraph.loadModulesGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import func PackageGraph.loadModulesGraph import class PackageModel.Manifest import struct PackageModel.ProductDescription import struct PackageModel.TargetDescription import func _InternalTestSupport.XCTAssertNoDiagnostics -@testable -import Commands +@testable import Commands import Testing import _InternalTestSupport @@ -31,7 +29,7 @@ import _InternalTestSupport struct MermaidPackageSerializerTests { @Test( .tags( - .TestSize.medium, //? + .TestSize.medium, //? ), ) func simplePackage() throws { @@ -51,7 +49,7 @@ struct MermaidPackageSerializerTests { TargetDescription(name: "ATarget"), TargetDescription(name: "ATargetTests", dependencies: ["ATarget"], type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -60,22 +58,24 @@ struct MermaidPackageSerializerTests { #expect(graph.packages.count == 1) let package = try #require(graph.packages.first) let serializer = MermaidPackageSerializer(package: package.underlying) - #expect(serializer.renderedMarkdown == """ - ```mermaid - flowchart TB - subgraph a - product:APackageTests[[APackageTests]]-->target:ATargetTests(ATargetTests) - product:ATarget[[ATarget]]-->target:ATarget(ATarget) - target:ATargetTests(ATargetTests)-->target:ATarget(ATarget) - end - ``` - - """) + #expect( + serializer.renderedMarkdown == """ + ```mermaid + flowchart TB + subgraph a + product:APackageTests[[APackageTests]]-->target:ATargetTests(ATargetTests) + product:ATarget[[ATarget]]-->target:ATarget(ATarget) + target:ATargetTests(ATargetTests)-->target:ATarget(ATarget) + end + ``` + + """ + ) } @Test( .tags( - .TestSize.medium, //? + .TestSize.medium, //? ), ) func dependenciesOnProducts() throws { @@ -95,7 +95,7 @@ struct MermaidPackageSerializerTests { displayName: "A", path: "/A", dependencies: [ - .localSourceControl(path: "/B", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/B", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription(name: "ATarget", dependencies: ["BLibrary"]), @@ -106,7 +106,7 @@ struct MermaidPackageSerializerTests { displayName: "B", path: "/B", products: [ - ProductDescription(name: "BLibrary", type: .library(.automatic), targets: ["BTarget"]), + ProductDescription(name: "BLibrary", type: .library(.automatic), targets: ["BTarget"]) ], targets: [ TargetDescription(name: "BTarget", dependencies: []), @@ -121,22 +121,24 @@ struct MermaidPackageSerializerTests { #expect(graph.packages.count == 2) let package = try #require(graph.package(for: .plain("A"))) let serializer = MermaidPackageSerializer(package: package.underlying) - #expect(serializer.renderedMarkdown == """ - ```mermaid - flowchart TB - subgraph a - product:APackageTests[[APackageTests]]-->target:ATargetTests(ATargetTests) - target:ATargetTests(ATargetTests)-->target:ATarget(ATarget) - target:ATarget(ATarget)-->BLibrary{{BLibrary}} - end - ``` - - """) + #expect( + serializer.renderedMarkdown == """ + ```mermaid + flowchart TB + subgraph a + product:APackageTests[[APackageTests]]-->target:ATargetTests(ATargetTests) + target:ATargetTests(ATargetTests)-->target:ATarget(ATarget) + target:ATarget(ATarget)-->BLibrary{{BLibrary}} + end + ``` + + """ + ) } @Test( .tags( - .TestSize.medium, //? + .TestSize.medium, //? ), ) func dependenciesOnPackages() throws { @@ -156,7 +158,7 @@ struct MermaidPackageSerializerTests { displayName: "A", path: "/A", dependencies: [ - .localSourceControl(path: "/B", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/B", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription(name: "ATarget", dependencies: [.product(name: "BLibrary", package: "B")]), @@ -167,7 +169,7 @@ struct MermaidPackageSerializerTests { displayName: "B", path: "/B", products: [ - ProductDescription(name: "BLibrary", type: .library(.automatic), targets: ["BTarget"]), + ProductDescription(name: "BLibrary", type: .library(.automatic), targets: ["BTarget"]) ], targets: [ TargetDescription(name: "BTarget", dependencies: []), @@ -182,19 +184,21 @@ struct MermaidPackageSerializerTests { #expect(graph.packages.count == 2) let package = try #require(graph.package(for: .plain("A"))) let serializer = MermaidPackageSerializer(package: package.underlying) - #expect(serializer.renderedMarkdown == """ - ```mermaid - flowchart TB - subgraph a - product:APackageTests[[APackageTests]]-->target:ATargetTests(ATargetTests) - target:ATargetTests(ATargetTests)-->target:ATarget(ATarget) - end - - subgraph B - target:ATarget(ATarget)-->BLibrary{{BLibrary}} - end - ``` - - """) + #expect( + serializer.renderedMarkdown == """ + ```mermaid + flowchart TB + subgraph a + product:APackageTests[[APackageTests]]-->target:ATargetTests(ATargetTests) + target:ATargetTests(ATargetTests)-->target:ATarget(ATarget) + end + + subgraph B + target:ATarget(ATarget)-->BLibrary{{BLibrary}} + end + ``` + + """ + ) } } diff --git a/Tests/CommandsTests/PackageCommandTests.swift b/Tests/CommandsTests/PackageCommandTests.swift index c0b9481f621..d6da1267d10 100644 --- a/Tests/CommandsTests/PackageCommandTests.swift +++ b/Tests/CommandsTests/PackageCommandTests.swift @@ -159,7 +159,7 @@ struct PackageCommandTests { func commandFailsSilentlyWhenFetchingPluginFails( data: BuildData, ) async throws { - try await fixture(name: "Miscellaneous/Plugins/MySourceGenPlugin") { fixturePath in // Contains only build-tool-plugins, therefore would not appear in available plugin commands. + try await fixture(name: "Miscellaneous/Plugins/MySourceGenPlugin") { fixturePath in // Contains only build-tool-plugins, therefore would not appear in available plugin commands. let (stdout, _) = try await execute( ["--help"], packagePath: fixturePath, @@ -1366,7 +1366,7 @@ struct PackageCommandTests { Issue.record("unexpected result") return } - #expect(`default`["name"]?.stringValue == "default") + #expect(`default`["name"]?.stringValue == "default") guard case .array(let enabledTraits) = `default`["enabledTraits"] else { Issue.record("unexpected result") return @@ -1383,7 +1383,7 @@ struct PackageCommandTests { Issue.record("unexpected result") return } - #expect(trait1["name"]?.stringValue == "trait1") + #expect(trait1["name"]?.stringValue == "trait1") guard case let third = contents[2] else { Issue.record("unexpected result") @@ -1393,7 +1393,7 @@ struct PackageCommandTests { Issue.record("unexpected result") return } - #expect(trait2["name"]?.stringValue == "trait2") + #expect(trait2["name"]?.stringValue == "trait2") // Show traits for the dependency based on its package id (textOutput, _) = try await execute( @@ -1428,7 +1428,7 @@ struct PackageCommandTests { Issue.record("unexpected result") return } - #expect(trait3["name"]?.stringValue == "trait3") + #expect(trait3["name"]?.stringValue == "trait3") } } @@ -2500,10 +2500,10 @@ struct PackageCommandTests { // executable do { _ = try await execute( - ["add-target", "client", "--dependencies", "MyLib", "OtherLib", "--type", "executable"], - packagePath: path, - configuration: data.config, - buildSystem: data.buildSystem, + ["add-target", "client", "--dependencies", "MyLib", "OtherLib", "--type", "executable"], + packagePath: path, + configuration: data.config, + buildSystem: data.buildSystem, ) let contents: String = try fs.readFileContents(manifest) @@ -2519,10 +2519,10 @@ struct PackageCommandTests { // library do { _ = try await execute( - ["add-target", "MyLib", "--type", "library"], - packagePath: path, - configuration: data.config, - buildSystem: data.buildSystem, + ["add-target", "MyLib", "--type", "library"], + packagePath: path, + configuration: data.config, + buildSystem: data.buildSystem, ) let contents: String = try fs.readFileContents(manifest) @@ -2537,10 +2537,10 @@ struct PackageCommandTests { // test do { _ = try await execute( - ["add-target", "MyTest", "--type", "test"], - packagePath: path, - configuration: data.config, - buildSystem: data.buildSystem, + ["add-target", "MyTest", "--type", "test"], + packagePath: path, + configuration: data.config, + buildSystem: data.buildSystem, ) let contents: String = try fs.readFileContents(manifest) @@ -2555,10 +2555,10 @@ struct PackageCommandTests { // macro + swift-syntax dependency do { _ = try await execute( - ["add-target", "MyMacro", "--type", "macro"], - packagePath: path, - configuration: data.config, - buildSystem: data.buildSystem, + ["add-target", "MyMacro", "--type", "macro"], + packagePath: path, + configuration: data.config, + buildSystem: data.buildSystem, ) let contents: String = try fs.readFileContents(manifest) @@ -3070,7 +3070,7 @@ struct PackageCommandTests { data: BuildData, ) async throws { try await withKnownIssue( - isIntermittent: ProcessInfo.isHostAmazonLinux2() //rdar://134238535 + isIntermittent: ProcessInfo.isHostAmazonLinux2() //rdar://134238535 ) { // Create a temporary directory without Package.swift try await fixture(name: "Miscellaneous") { fixturePath in @@ -3255,7 +3255,6 @@ struct PackageCommandTests { let value = try await AsyncProcess.checkNonZeroExit(arguments: exec).spm_chomp() #expect(value == "\(5)") - // Get path to `bar` checkout. let barPath = try SwiftPM.packagePath(for: "bar", packageRoot: fooPath) @@ -3291,7 +3290,7 @@ struct PackageCommandTests { ]! #expect(resolvedPackage.packageRef.identity == PackageIdentity(path: path)) guard case .localSourceControl(let path) = resolvedPackage.packageRef.kind, - path.pathString.hasSuffix(pkg) + path.pathString.hasSuffix(pkg) else { Issue.record("invalid resolved package location \(path)") return @@ -4527,8 +4526,8 @@ struct PackageCommandTests { @Test( .tags( - .Feature.Command.Build, - .Feature.PackageType.BuildToolPlugin + .Feature.Command.Build, + .Feature.PackageType.BuildToolPlugin ), .requiresSwiftConcurrencySupport, arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), @@ -5269,8 +5268,8 @@ struct PackageCommandTests { // Test reporting of plugin diagnostic messages at different verbosity levels @Test( .tags( - .Feature.Command.Build, - .Feature.PackageType.CommandPlugin + .Feature.Command.Build, + .Feature.PackageType.CommandPlugin ), .requiresSwiftConcurrencySupport, .issue( @@ -5464,8 +5463,8 @@ struct PackageCommandTests { // Test target builds requested by a command plugin @Test( .tags( - .Feature.Command.Run, - .Feature.PackageType.CommandPlugin + .Feature.Command.Run, + .Feature.PackageType.CommandPlugin ), .IssueWindowsRelativePathAssert, .requiresSwiftConcurrencySupport, @@ -5499,8 +5498,8 @@ struct PackageCommandTests { // Test target builds requested by a command plugin @Test( .tags( - .Feature.Command.Run, - .Feature.PackageType.CommandPlugin + .Feature.Command.Run, + .Feature.PackageType.CommandPlugin ), .IssueWindowsRelativePathAssert, .requiresSwiftConcurrencySupport, @@ -5538,8 +5537,8 @@ struct PackageCommandTests { // Test target builds requested by a command plugin @Test( .tags( - .Feature.Command.Run, - .Feature.PackageType.CommandPlugin + .Feature.Command.Run, + .Feature.PackageType.CommandPlugin ), .IssueWindowsRelativePathAssert, .requiresSwiftConcurrencySupport, @@ -5576,8 +5575,8 @@ struct PackageCommandTests { // Test target builds requested by a command plugin @Test( .tags( - .Feature.Command.Run, - .Feature.PackageType.CommandPlugin + .Feature.Command.Run, + .Feature.PackageType.CommandPlugin ), .IssueWindowsRelativePathAssert, .requiresSwiftConcurrencySupport, @@ -5617,8 +5616,8 @@ struct PackageCommandTests { @Test( .tags( - .Feature.Command.Run, - .Feature.PackageType.CommandPlugin + .Feature.Command.Run, + .Feature.PackageType.CommandPlugin ), .IssueWindowsRelativePathAssert, arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), @@ -5646,8 +5645,8 @@ struct PackageCommandTests { @Test( .tags( - .Feature.Command.Run, - .Feature.PackageType.CommandPlugin + .Feature.Command.Run, + .Feature.PackageType.CommandPlugin ), .IssueWindowsRelativePathAssert, arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), @@ -5674,8 +5673,8 @@ struct PackageCommandTests { @Test( .tags( - .Feature.Command.Run, - .Feature.PackageType.CommandPlugin + .Feature.Command.Run, + .Feature.PackageType.CommandPlugin ), .IssueWindowsRelativePathAssert, .tags( @@ -5707,8 +5706,8 @@ struct PackageCommandTests { // Test logging of builds initiated by a command plugin @Test( .tags( - .Feature.Command.Build, - .Feature.PackageType.CommandPlugin + .Feature.Command.Build, + .Feature.PackageType.CommandPlugin ), .IssueWindowsRelativePathAssert, .requiresSwiftConcurrencySupport, @@ -6458,7 +6457,8 @@ struct PackageCommandTests { } } } when: { - let shouldSkip: Bool = (ProcessInfo.hostOperatingSystem == .windows && data.buildSystem == .swiftbuild) + let shouldSkip: Bool = + (ProcessInfo.hostOperatingSystem == .windows && data.buildSystem == .swiftbuild) || !CiEnvironment.runningInSmokeTestPipeline #if compiler(>=6.3) @@ -7338,13 +7338,13 @@ struct PackageCommandTests { ) switch data.buildSystem { case .native: - #expect(!stdout.contains("Compiling plugin MyBuildToolPlugin"), "stderr: \(stderr)") - #expect(stdout.contains("Compiling plugin MyCommandPlugin"), "stderr: \(stderr)") - case .swiftbuild: + #expect(!stdout.contains("Compiling plugin MyBuildToolPlugin"), "stderr: \(stderr)") + #expect(stdout.contains("Compiling plugin MyCommandPlugin"), "stderr: \(stderr)") + case .swiftbuild: // nothing specific break - case .xcode: - Issue.record("Test expected have not been considered") + case .xcode: + Issue.record("Test expected have not been considered") } #expect(!stdout.contains("Building for \(data.config.buildFor)..."), "stderr: \(stderr)") } diff --git a/Tests/CommandsTests/PackageRegistryCommandTests.swift b/Tests/CommandsTests/PackageRegistryCommandTests.swift index fa47d13a46f..c370bc80780 100644 --- a/Tests/CommandsTests/PackageRegistryCommandTests.swift +++ b/Tests/CommandsTests/PackageRegistryCommandTests.swift @@ -20,7 +20,7 @@ import PackageRegistry import struct SPMBuildCore.BuildSystemProvider import PackageSigning import _InternalTestSupport -import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported +import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported import Workspace import Testing @@ -69,7 +69,6 @@ struct PackageRegistryCommandTests { #expect(stdout.contains("USAGE: swift package-registry"), "got stdout: '\(stdout)'") } - @Test( .tags( .TestSize.large, @@ -114,7 +113,8 @@ struct PackageRegistryCommandTests { .Feature.Command.PackageRegistry.Set, .Feature.Command.PackageRegistry.Unset, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func localConfiguration( buildSystem: BuildSystemProvider.Kind, @@ -245,7 +245,8 @@ struct PackageRegistryCommandTests { .TestSize.large, .Feature.Command.PackageRegistry.Set, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func setMissingURL( buildSystem: BuildSystemProvider.Kind, @@ -279,7 +280,8 @@ struct PackageRegistryCommandTests { .TestSize.large, .Feature.Command.PackageRegistry.Set, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func setInvalidURL( buildSystem: BuildSystemProvider.Kind, @@ -313,7 +315,8 @@ struct PackageRegistryCommandTests { .TestSize.large, .Feature.Command.PackageRegistry.Set, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func setInsecureURL( buildSystem: BuildSystemProvider.Kind, @@ -347,7 +350,8 @@ struct PackageRegistryCommandTests { .TestSize.large, .Feature.Command.PackageRegistry.Set, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func setAllowedInsecureURL( buildSystem: BuildSystemProvider.Kind, @@ -379,7 +383,8 @@ struct PackageRegistryCommandTests { .TestSize.large, .Feature.Command.PackageRegistry.Set, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func setInvalidScope( buildSystem: BuildSystemProvider.Kind, @@ -416,7 +421,8 @@ struct PackageRegistryCommandTests { .Feature.Command.PackageRegistry.Set, .Feature.Command.PackageRegistry.Unset, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func unsetMissingEntry( buildSystem: BuildSystemProvider.Kind, @@ -474,7 +480,8 @@ struct PackageRegistryCommandTests { .TestSize.large, ), .requiresWorkingDirectorySupport, - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func archiving( buildSystem: BuildSystemProvider.Kind, @@ -601,14 +608,14 @@ struct PackageRegistryCommandTests { .Feature.Command.PackageRegistry.Publish, ), .requiresWorkingDirectorySupport, - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func publishingToHTTPRegistry( buildSystem: BuildSystemProvider.Kind, config: BuildConfiguration, ) throws { - let packageIdentity = "test.my-package" let version = "0.1.0" let registryURL = "http://packages.example.com" @@ -653,7 +660,8 @@ struct PackageRegistryCommandTests { .Feature.Command.PackageRegistry.Publish, ), .requiresWorkingDirectorySupport, - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func publishingToAllowedHTTPRegistry( buildSystem: BuildSystemProvider.Kind, @@ -748,7 +756,8 @@ struct PackageRegistryCommandTests { .TestSize.large, .Feature.Command.PackageRegistry.Publish, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func publishingUnsignedPackage( buildSystem: BuildSystemProvider.Kind, @@ -916,7 +925,8 @@ struct PackageRegistryCommandTests { .TestSize.large, .Feature.Command.PackageRegistry.Publish, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) func publishingSignedPackage( @@ -1230,8 +1240,10 @@ struct PackageRegistryCommandTests { ) // no metadata so no signature - #expect(!localFileSystem - .exists(workingDirectory.appending("\(packageIdentity)-\(version)-metadata.sig"))) + #expect( + !localFileSystem + .exists(workingDirectory.appending("\(packageIdentity)-\(version)-metadata.sig")) + ) // manifest signatures let manifest = try localFileSystem.readFileContents(manifestPath).contents @@ -1282,8 +1294,9 @@ struct PackageRegistryCommandTests { arguments: [ LogingUrlData(loginApiPath: nil, expectedComponent: "login"), LogingUrlData(loginApiPath: "/secret-sign-in", expectedComponent: "secret-sign-in"), - ], [ - "https://packages.example.com", + ], + [ + "https://packages.example.com" // "https://packages.example.com:8081", ] ) @@ -1293,8 +1306,8 @@ struct PackageRegistryCommandTests { ) async throws { let registryURL = try #require(URL(string: registryUrl), "Failed to instantiate registry URL") - let actualUrl = try PackageRegistryCommand.Login.loginURL(from: registryURL, loginAPIPath: data.loginApiPath) - let actualString = actualUrl.absoluteString + let actualUrl = try PackageRegistryCommand.Login.loginURL(from: registryURL, loginAPIPath: data.loginApiPath) + let actualString = actualUrl.absoluteString #expect(actualString == "\(registryUrl)/\(data.expectedComponent)") } @@ -1326,7 +1339,8 @@ struct PackageRegistryCommandTests { private func getRoots() throws -> [[UInt8]] { try fixture(name: "Signing", createGitRepo: false) { fixturePath in - let rootCA = try localFileSystem + let rootCA = + try localFileSystem .readFileContents(fixturePath.appending(components: "Certificates", "TestRootCA.cer")).contents return [rootCA] } diff --git a/Tests/CommandsTests/RunCommandTests.swift b/Tests/CommandsTests/RunCommandTests.swift index 7da21d8fae7..169a6e24156 100644 --- a/Tests/CommandsTests/RunCommandTests.swift +++ b/Tests/CommandsTests/RunCommandTests.swift @@ -24,7 +24,7 @@ import enum PackageModel.BuildConfiguration import class Basics.AsyncProcess @Suite( - .serialized, // to limit the number of swift executable running. + .serialized, // to limit the number of swift executable running. .tags( Tag.TestSize.large, Tag.Feature.Command.Run, @@ -53,7 +53,7 @@ struct RunCommandTests { buildSystem: BuildSystemProvider.Kind ) async throws { let stdout = try await execute(["-help"], buildSystem: buildSystem).stdout - + #expect(stdout.contains("USAGE: swift run ") || stdout.contains("USAGE: swift run []"), "got stdout:\n \(stdout)") } @@ -107,42 +107,42 @@ struct RunCommandTests { buildSystem: BuildSystemProvider.Kind, ) async throws { try await withKnownIssue { - try await fixture(name: "Miscellaneous/EchoExecutable") { fixturePath in - #if os(Windows) - let win32 = ".win32" - #else - let win32 = "" - #endif - let (stdout, stderr) = try await execute( + try await fixture(name: "Miscellaneous/EchoExecutable") { fixturePath in + #if os(Windows) + let win32 = ".win32" + #else + let win32 = "" + #endif + let (stdout, stderr) = try await execute( ["--toolset", "\(fixturePath.appending("toolset\(win32).json").pathString)"], packagePath: fixturePath, buildSystem: buildSystem, ) - // We only expect tool's output on the stdout stream. - #expect(stdout.contains("\(fixturePath.appending(".build").pathString)")) - #expect(stdout.contains("sentinel")) + // We only expect tool's output on the stdout stream. + #expect(stdout.contains("\(fixturePath.appending(".build").pathString)")) + #expect(stdout.contains("sentinel")) - // swift-build-tool output should go to stderr. - withKnownIssue { - #expect(stderr.contains("Compiling")) - } when: { - buildSystem == .swiftbuild - } - withKnownIssue { - #expect(stderr.contains("Linking")) - } when: { - buildSystem == .swiftbuild + // swift-build-tool output should go to stderr. + withKnownIssue { + #expect(stderr.contains("Compiling")) + } when: { + buildSystem == .swiftbuild + } + withKnownIssue { + #expect(stderr.contains("Linking")) + } when: { + buildSystem == .swiftbuild + } } - } } when: { (.swiftbuild == buildSystem && ProcessInfo.hostOperatingSystem == .windows) - || (.native == buildSystem && ProcessInfo.hostOperatingSystem == .windows && CiEnvironment.runningInSmokeTestPipeline) + || (.native == buildSystem && ProcessInfo.hostOperatingSystem == .windows && CiEnvironment.runningInSmokeTestPipeline) } } @Test( - .tags( + .tags( .Feature.TargetType.Executable, ), .IssueWindowsPathTestsFailures, @@ -161,9 +161,13 @@ struct RunCommandTests { ) // We only expect tool's output on the stdout stream. - #expect(stdout.contains(""" - "1" "--hello" "world" - """)) + #expect( + stdout.contains( + """ + "1" "--hello" "world" + """ + ) + ) // swift-build-tool output should go to stderr. withKnownIssue { @@ -179,7 +183,7 @@ struct RunCommandTests { } } when: { (.windows == ProcessInfo.hostOperatingSystem && buildSystem == .swiftbuild) - || (.windows == ProcessInfo.hostOperatingSystem && buildSystem == .native && CiEnvironment.runningInSmokeTestPipeline) + || (.windows == ProcessInfo.hostOperatingSystem && buildSystem == .native && CiEnvironment.runningInSmokeTestPipeline) } } @@ -192,7 +196,7 @@ struct RunCommandTests { buildSystem: BuildSystemProvider.Kind, ) async throws { try await fixture(name: "Miscellaneous/EchoExecutable") { fixturePath in - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await execute(["unknown"], packagePath: fixturePath, buildSystem: buildSystem) } guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = try #require(error) else { @@ -208,9 +212,8 @@ struct RunCommandTests { } } - @Test( - .tags( + .tags( .Feature.TargetType.Executable, ), .SWBINTTODO("Swift run using Swift Build does not output executable content to the terminal"), @@ -221,34 +224,33 @@ struct RunCommandTests { buildSystem: BuildSystemProvider.Kind, ) async throws { try await withKnownIssue { - try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in - let error = await #expect(throws: SwiftPMError.self ) { - try await execute(packagePath: fixturePath, buildSystem: buildSystem) - } - guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = try #require(error) else { - Issue.record("Incorrect error was raised.") - return - } + let error = await #expect(throws: SwiftPMError.self) { + try await execute(packagePath: fixturePath, buildSystem: buildSystem) + } + guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return + } - #expect( - stderr.contains("error: multiple executable products available: exec1, exec2"), - "got stdout: \(stdout), stderr: \(stderr)", - ) + #expect( + stderr.contains("error: multiple executable products available: exec1, exec2"), + "got stdout: \(stdout), stderr: \(stderr)", + ) - var (runOutput, _) = try await execute(["exec1"], packagePath: fixturePath, buildSystem: buildSystem) - #expect(runOutput.contains("1")) + var (runOutput, _) = try await execute(["exec1"], packagePath: fixturePath, buildSystem: buildSystem) + #expect(runOutput.contains("1")) - (runOutput, _) = try await execute(["exec2"], packagePath: fixturePath, buildSystem: buildSystem) - #expect(runOutput.contains("2")) - } + (runOutput, _) = try await execute(["exec2"], packagePath: fixturePath, buildSystem: buildSystem) + #expect(runOutput.contains("2")) + } } when: { ([.windows].contains(ProcessInfo.hostOperatingSystem) && buildSystem == .swiftbuild && CiEnvironment.runningInSelfHostedPipeline) - || (.windows == ProcessInfo.hostOperatingSystem && [.native, .swiftbuild].contains(buildSystem) && CiEnvironment.runningInSmokeTestPipeline) + || (.windows == ProcessInfo.hostOperatingSystem && [.native, .swiftbuild].contains(buildSystem) && CiEnvironment.runningInSmokeTestPipeline) } } - @Test( .tags( .Feature.TargetType.Executable, @@ -305,7 +307,7 @@ struct RunCommandTests { buildSystem: BuildSystemProvider.Kind, ) async throws { try await fixture(name: "Miscellaneous/EchoExecutable") { fixturePath in - let error = await #expect(throws: SwiftPMError.self ) { + let error = await #expect(throws: SwiftPMError.self) { try await execute(["--build-tests", "--skip-build"], packagePath: fixturePath, buildSystem: buildSystem) } guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = try #require(error) else { @@ -336,14 +338,14 @@ struct RunCommandTests { try localFileSystem.writeFileContents( mainFilePath, string: """ - import Foundation + import Foundation - print("sleeping") - fflush(stdout) + print("sleeping") + fflush(stdout) - Thread.sleep(forTimeInterval: 10) - print("done") - """ + Thread.sleep(forTimeInterval: 10) + print("done") + """ ) let sync = DispatchGroup() @@ -369,11 +371,11 @@ struct RunCommandTests { // check for interrupt result let result = try process.waitUntilExit() - #if os(Windows) - #expect(result.exitStatus == .abnormal(exception: 2)) - #else - #expect(result.exitStatus == .signalled(signal: SIGINT)) - #endif + #if os(Windows) + #expect(result.exitStatus == .abnormal(exception: 2)) + #else + #expect(result.exitStatus == .signalled(signal: SIGINT)) + #endif } class OutputHandler { @@ -398,7 +400,7 @@ struct RunCommandTests { let newBuffer = buffer + output self.state = processOutput(newBuffer) case .done: - break //noop + break //noop } } @@ -431,7 +433,8 @@ struct RunCommandTests { .issue("https://github.com/swiftlang/swift-package-manager/issues/8844", relationship: .verifies), .issue("https://github.com/swiftlang/swift-package-manager/issues/8911", relationship: .defect), .issue("https://github.com/swiftlang/swift-package-manager/issues/8912", relationship: .defect), - arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases + arguments: SupportedBuildSystemOnPlatform, + BuildConfiguration.allCases ) func swiftRunQuietLogLevel( buildSystem: BuildSystemProvider.Kind, @@ -440,27 +443,28 @@ struct RunCommandTests { try await withKnownIssue { // GIVEN we have a simple test package try await fixture(name: "Miscellaneous/SwiftRun") { fixturePath in - //WHEN we run with the --quiet option - let (stdout, stderr) = try await executeSwiftRun( - fixturePath, - nil, - configuration: configuration, - extraArgs: ["--quiet"], - buildSystem: buildSystem - ) - // THEN we should not see any output in stderr + //WHEN we run with the --quiet option + let (stdout, stderr) = try await executeSwiftRun( + fixturePath, + nil, + configuration: configuration, + extraArgs: ["--quiet"], + buildSystem: buildSystem + ) + // THEN we should not see any output in stderr #expect(stderr.isEmpty) - // AND no content in stdout + // AND no content in stdout #expect(stdout == "done\n") - } + } } when: { - (CiEnvironment.runningInSmokeTestPipeline && ProcessInfo.hostOperatingSystem == .windows) + (CiEnvironment.runningInSmokeTestPipeline && ProcessInfo.hostOperatingSystem == .windows) } } @Test( .bug("https://github.com/swiftlang/swift-package-manager/issues/8844"), - arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases + arguments: SupportedBuildSystemOnPlatform, + BuildConfiguration.allCases ) func swiftRunQuietLogLevelWithError( buildSystem: BuildSystemProvider.Kind, @@ -473,8 +477,8 @@ struct RunCommandTests { try localFileSystem.writeFileContents( mainFilePath, string: """ - print("done" - """ + print("done" + """ ) //WHEN we run with the --quiet option diff --git a/Tests/CommandsTests/Sanitizer+ExtensionsTests.swift b/Tests/CommandsTests/Sanitizer+ExtensionsTests.swift index c7008f269b1..282f8266ed8 100644 --- a/Tests/CommandsTests/Sanitizer+ExtensionsTests.swift +++ b/Tests/CommandsTests/Sanitizer+ExtensionsTests.swift @@ -23,7 +23,7 @@ struct SanitizerExtensionTests { arguments: Sanitizer.allCases ) func creatingSanitizers(sanitizer: Sanitizer) throws { - #expect(sanitizer == Sanitizer(argument: sanitizer.shortName)) + #expect(sanitizer == Sanitizer(argument: sanitizer.shortName)) } @Test diff --git a/Tests/CommandsTests/SwiftCommandStateTests.swift b/Tests/CommandsTests/SwiftCommandStateTests.swift index 17b0a8f2e91..6f541d1e2c5 100644 --- a/Tests/CommandsTests/SwiftCommandStateTests.swift +++ b/Tests/CommandsTests/SwiftCommandStateTests.swift @@ -15,8 +15,7 @@ @testable import Commands @testable import CoreCommands -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import func PackageGraph.loadModulesGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import func PackageGraph.loadModulesGraph import _InternalTestSupport @testable import PackageModel @@ -40,7 +39,7 @@ final class SwiftCommandStateTests: XCTestCase { if let originalWorkingDirectory { try? localFileSystem.changeCurrentWorkingDirectory(to: originalWorkingDirectory) } - } + } func testSeverityEnum() async throws { try fixtureXCTest(name: "Miscellaneous/Simple") { _ in @@ -259,24 +258,24 @@ final class SwiftCommandStateTests: XCTestCase { let tool = try SwiftCommandState.makeMockState(options: options) // There is only one AuthorizationProvider depending on platform -#if canImport(Security) - let keychainProvider = try tool.getRegistryAuthorizationProvider() as? KeychainAuthorizationProvider - XCTAssertNotNil(keychainProvider) -#else - let netrcProvider = try tool.getRegistryAuthorizationProvider() as? NetrcAuthorizationProvider - XCTAssertNotNil(netrcProvider) - XCTAssertEqual(try netrcProvider.map { try resolveSymlinks($0.path) }, try resolveSymlinks(customPath)) - - let auth = try tool.getRegistryAuthorizationProvider()?.authentication(for: "https://mymachine.labkey.org") - XCTAssertEqual(auth?.user, "custom@labkey.org") - XCTAssertEqual(auth?.password, "custom") - - // delete it - try localFileSystem.removeFileTree(customPath) - XCTAssertThrowsError(try tool.getRegistryAuthorizationProvider(), "error expected") { error in - XCTAssertEqual(error as? StringError, StringError("did not find netrc file at \(customPath)")) - } -#endif + #if canImport(Security) + let keychainProvider = try tool.getRegistryAuthorizationProvider() as? KeychainAuthorizationProvider + XCTAssertNotNil(keychainProvider) + #else + let netrcProvider = try tool.getRegistryAuthorizationProvider() as? NetrcAuthorizationProvider + XCTAssertNotNil(netrcProvider) + XCTAssertEqual(try netrcProvider.map { try resolveSymlinks($0.path) }, try resolveSymlinks(customPath)) + + let auth = try tool.getRegistryAuthorizationProvider()?.authentication(for: "https://mymachine.labkey.org") + XCTAssertEqual(auth?.user, "custom@labkey.org") + XCTAssertEqual(auth?.password, "custom") + + // delete it + try localFileSystem.removeFileTree(customPath) + XCTAssertThrowsError(try tool.getRegistryAuthorizationProvider(), "error expected") { error in + XCTAssertEqual(error as? StringError, StringError("did not find netrc file at \(customPath)")) + } + #endif } // Tests should not modify user's home dir .netrc so leaving that out intentionally @@ -285,15 +284,21 @@ final class SwiftCommandStateTests: XCTestCase { func testDebugFormatFlags() async throws { let fs = InMemoryFileSystem(emptyFiles: [ - "/Pkg/Sources/exe/main.swift", + "/Pkg/Sources/exe/main.swift" ]) let observer = ObservabilitySystem.makeForTesting() - let graph = try loadModulesGraph(fileSystem: fs, manifests: [ - Manifest.createRootManifest(displayName: "Pkg", - path: "/Pkg", - targets: [TargetDescription(name: "exe")]) - ], observabilityScope: observer.topScope) + let graph = try loadModulesGraph( + fileSystem: fs, + manifests: [ + Manifest.createRootManifest( + displayName: "Pkg", + path: "/Pkg", + targets: [TargetDescription(name: "exe")] + ) + ], + observabilityScope: observer.topScope + ) var plan: BuildPlan @@ -307,8 +312,10 @@ final class SwiftCommandStateTests: XCTestCase { fileSystem: fs, observabilityScope: observer.topScope ) - try XCTAssertMatch(plan.buildProducts.compactMap { $0 as? Build.ProductBuildDescription }.first?.linkArguments() ?? [], - [.anySequence, "-g", "-use-ld=lld", "-Xlinker", "-debug:dwarf"]) + try XCTAssertMatch( + plan.buildProducts.compactMap { $0 as? Build.ProductBuildDescription }.first?.linkArguments() ?? [], + [.anySequence, "-g", "-use-ld=lld", "-Xlinker", "-debug:dwarf"] + ) /* -debug-info-format codeview */ let explicitCodeViewOptions = try GlobalOptions.parse(["--triple", "x86_64-unknown-windows-msvc", "-debug-info-format", "codeview"]) @@ -321,8 +328,10 @@ final class SwiftCommandStateTests: XCTestCase { fileSystem: fs, observabilityScope: observer.topScope ) - try XCTAssertMatch(plan.buildProducts.compactMap { $0 as? Build.ProductBuildDescription }.first?.linkArguments() ?? [], - [.anySequence, "-g", "-debug-info-format=codeview", "-Xlinker", "-debug"]) + try XCTAssertMatch( + plan.buildProducts.compactMap { $0 as? Build.ProductBuildDescription }.first?.linkArguments() ?? [], + [.anySequence, "-g", "-debug-info-format=codeview", "-Xlinker", "-debug"] + ) // Explicitly pass Linux as when the `SwiftCommandState` tests are enabled on // Windows, this would fail otherwise as CodeView is supported on the @@ -344,8 +353,10 @@ final class SwiftCommandStateTests: XCTestCase { fileSystem: fs, observabilityScope: observer.topScope ) - try XCTAssertMatch(plan.buildProducts.compactMap { $0 as? Build.ProductBuildDescription }.first?.linkArguments() ?? [], - [.anySequence, "-g", "-use-ld=lld", "-Xlinker", "-debug:dwarf"]) + try XCTAssertMatch( + plan.buildProducts.compactMap { $0 as? Build.ProductBuildDescription }.first?.linkArguments() ?? [], + [.anySequence, "-g", "-use-ld=lld", "-Xlinker", "-debug:dwarf"] + ) /* -debug-info-format none */ let explicitNoDebugInfoOptions = try GlobalOptions.parse(["--triple", "x86_64-unknown-windows-msvc", "-debug-info-format", "none"]) @@ -357,8 +368,10 @@ final class SwiftCommandStateTests: XCTestCase { fileSystem: fs, observabilityScope: observer.topScope ) - try XCTAssertMatch(plan.buildProducts.compactMap { $0 as? Build.ProductBuildDescription }.first?.linkArguments() ?? [], - [.anySequence, "-gnone", .anySequence]) + try XCTAssertMatch( + plan.buildProducts.compactMap { $0 as? Build.ProductBuildDescription }.first?.linkArguments() ?? [], + [.anySequence, "-gnone", .anySequence] + ) } func testToolchainOption() async throws { @@ -374,10 +387,10 @@ final class SwiftCommandStateTests: XCTestCase { hostSwiftcPath.pathString, hostArPath.pathString, targetSwiftcPath.pathString, - targetArPath.pathString + targetArPath.pathString, ]) - for path in [hostSwiftcPath, hostArPath, targetSwiftcPath, targetArPath,] { + for path in [hostSwiftcPath, hostArPath, targetSwiftcPath, targetArPath] { try fs.updatePermissions(path, isExecutable: true) } @@ -440,19 +453,22 @@ final class SwiftCommandStateTests: XCTestCase { hostSwiftcPath.pathString, hostArPath.pathString, targetSwiftcPath.pathString, - targetArPath.pathString + targetArPath.pathString, ]) - for path in [hostSwiftcPath, hostArPath, targetSwiftcPath, targetArPath,] { + for path in [hostSwiftcPath, hostArPath, targetSwiftcPath, targetArPath] { try fs.updatePermissions(path, isExecutable: true) } - try fs.writeFileContents("/toolset.json", string: """ - { - "schemaVersion": "1.0", - "rootPath": "\(targetToolchainPath)" - } - """) + try fs.writeFileContents( + "/toolset.json", + string: """ + { + "schemaVersion": "1.0", + "rootPath": "\(targetToolchainPath)" + } + """ + ) let options = try GlobalOptions.parse(["--toolset", "/toolset.json"]) let swiftCommandState = try SwiftCommandState.makeMockState( @@ -489,29 +505,35 @@ final class SwiftCommandStateTests: XCTestCase { hostArPath.pathString, targetSwiftcPath.pathString, targetArPath.pathString, - targetClangPath.pathString + targetClangPath.pathString, ]) - for path in [hostSwiftcPath, hostArPath, targetSwiftcPath, targetArPath, targetClangPath,] { + for path in [hostSwiftcPath, hostArPath, targetSwiftcPath, targetArPath, targetClangPath] { try fs.updatePermissions(path, isExecutable: true) } - try fs.writeFileContents("/toolset1.json", string: """ - { - "schemaVersion": "1.0", - "rootPath": "\(targetToolchainPath1)" - } - """) + try fs.writeFileContents( + "/toolset1.json", + string: """ + { + "schemaVersion": "1.0", + "rootPath": "\(targetToolchainPath1)" + } + """ + ) - try fs.writeFileContents("/toolset2.json", string: """ - { - "schemaVersion": "1.0", - "rootPath": "\(targetToolchainPath2)" - } - """) + try fs.writeFileContents( + "/toolset2.json", + string: """ + { + "schemaVersion": "1.0", + "rootPath": "\(targetToolchainPath2)" + } + """ + ) let options = try GlobalOptions.parse([ - "--toolset", "/toolset1.json", "--toolset", "/toolset2.json" + "--toolset", "/toolset1.json", "--toolset", "/toolset2.json", ]) let swiftCommandState = try SwiftCommandState.makeMockState( options: options, diff --git a/Tests/CommandsTests/TestCommandTests.swift b/Tests/CommandsTests/TestCommandTests.swift index 38961e48428..09f8af025bc 100644 --- a/Tests/CommandsTests/TestCommandTests.swift +++ b/Tests/CommandsTests/TestCommandTests.swift @@ -47,7 +47,8 @@ struct TestCommandTests { } @Test( - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func usage( buildSystem: BuildSystemProvider.Kind, @@ -62,7 +63,8 @@ struct TestCommandTests { } @Test( - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func experimentalXunitMessageFailureArgumentIsHidden( buildSystem: BuildSystemProvider.Kind, @@ -84,7 +86,8 @@ struct TestCommandTests { } @Test( - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func seeAlso( buildSystem: BuildSystemProvider.Kind, @@ -99,7 +102,8 @@ struct TestCommandTests { } @Test( - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func version( buildSystem: BuildSystemProvider.Kind, @@ -154,24 +158,25 @@ struct TestCommandTests { withKnownIssue { #expect(stderr.contains("Compiling")) } when: { - buildSystem == .swiftbuild // && ProcessInfo.hostOperatingSystem != .macOS + buildSystem == .swiftbuild // && ProcessInfo.hostOperatingSystem != .macOS } withKnownIssue { #expect(stderr.contains("Linking")) } when: { - buildSystem == .swiftbuild // && ProcessInfo.hostOperatingSystem != .macOS + buildSystem == .swiftbuild // && ProcessInfo.hostOperatingSystem != .macOS } } } when: { (buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows) - || (buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .linux && CiEnvironment.runningInSmokeTestPipeline) - || (buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .linux && CiEnvironment.runningInSelfHostedPipeline) // error: SwiftCompile normal x86_64 /tmp/Miscellaneous_EchoExecutable.sxkNTX/Miscellaneous_EchoExecutable/.build/x86_64-unknown-linux-gnu/Intermediates.noindex/EchoExecutable.build/Debug-linux/TestSuite-test-runner.build/DerivedSources/test_entry_point.swift failed with a nonzero exit code + || (buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .linux && CiEnvironment.runningInSmokeTestPipeline) + || (buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .linux && CiEnvironment.runningInSelfHostedPipeline) // error: SwiftCompile normal x86_64 /tmp/Miscellaneous_EchoExecutable.sxkNTX/Miscellaneous_EchoExecutable/.build/x86_64-unknown-linux-gnu/Intermediates.noindex/EchoExecutable.build/Debug-linux/TestSuite-test-runner.build/DerivedSources/test_entry_point.swift failed with a nonzero exit code } } @Test( - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func numWorkersParallelRequirement( buildSystem: BuildSystemProvider.Kind, @@ -199,7 +204,8 @@ struct TestCommandTests { } @Test( - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func numWorkersValueSetToZeroRaisesAnError( buildSystem: BuildSystemProvider.Kind, @@ -229,7 +235,8 @@ struct TestCommandTests { .tags( .Feature.TargetType.Executable, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func enableDisableTestabilityDefaultShouldRunWithTestability( buildSystem: BuildSystemProvider.Kind, @@ -251,7 +258,7 @@ struct TestCommandTests { } } when: { // || (buildSystem == .swiftbuild && .windows == ProcessInfo.hostOperatingSystem && CiEnvironment.runningInSelfHostedPipeline) - (buildSystem == .swiftbuild && .windows == ProcessInfo.hostOperatingSystem ) + (buildSystem == .swiftbuild && .windows == ProcessInfo.hostOperatingSystem) } } @@ -260,7 +267,8 @@ struct TestCommandTests { .Feature.TargetType.Executable, ), .SWBINTTODO("Test currently fails due to 'error: build failed'"), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func enableDisableTestabilityDisabled( buildSystem: BuildSystemProvider.Kind, @@ -296,7 +304,8 @@ struct TestCommandTests { .tags( .Feature.TargetType.Executable, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func enableDisableTestabilityEnabled( buildSystem: BuildSystemProvider.Kind, @@ -323,7 +332,8 @@ struct TestCommandTests { ), .issue("https://github.com/swiftlang/swift-package-manager/issues/8479", relationship: .defect), .SWBINTTODO("Result XML could not be found. The build fails because of missing test helper generation logic for non-macOS platforms"), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func swiftTestParallel_SerialTesting( buildSystem: BuildSystemProvider.Kind, @@ -361,7 +371,8 @@ struct TestCommandTests { ), .issue("https://github.com/swiftlang/swift-package-manager/issues/8479", relationship: .defect), .SWBINTTODO("Result XML could not be found. The build fails because of missing test helper generation logic for non-macOS platforms"), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func swiftTestParallel_NoParallelArgument( buildSystem: BuildSystemProvider.Kind, @@ -391,13 +402,14 @@ struct TestCommandTests { } @Test( - .tags( + .tags( .Feature.TargetType.Executable, .Feature.CommandLineArguments.TestParallel, ), .issue("https://github.com/swiftlang/swift-package-manager/issues/8479", relationship: .defect), .SWBINTTODO("Result XML could not be found. The build fails because of missing test helper generation logic for non-macOS platforms"), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func swiftTestParallel_ParallelArgument( buildSystem: BuildSystemProvider.Kind, @@ -411,7 +423,8 @@ struct TestCommandTests { ["--parallel"], packagePath: fixturePath, configuration: configuration, - buildSystem: buildSystem) + buildSystem: buildSystem + ) } guard case SwiftPMError.executionFailure(_, let stdout, _) = try #require(error) else { Issue.record("Incorrect error was raised.") @@ -424,7 +437,7 @@ struct TestCommandTests { #expect(stdout.contains("[3/3]")) } } when: { - [ .windows].contains(ProcessInfo.hostOperatingSystem) && buildSystem == .swiftbuild + [.windows].contains(ProcessInfo.hostOperatingSystem) && buildSystem == .swiftbuild } } @@ -436,7 +449,8 @@ struct TestCommandTests { ), .issue("https://github.com/swiftlang/swift-package-manager/issues/8479", relationship: .defect), .SWBINTTODO("Result XML could not be found. The build fails because of missing test helper generation logic for non-macOS platforms"), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func swiftTestParallel_ParallelArgumentWithXunitOutputGeneration( buildSystem: BuildSystemProvider.Kind, @@ -490,7 +504,8 @@ struct TestCommandTests { ), .issue("https://github.com/swiftlang/swift-package-manager/issues/8479", relationship: .defect), .SWBINTTODO("Result XML could not be found. The build fails because of missing test helper generation logic for non-macOS platforms"), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func swiftTestXMLOutputWhenEmpty( buildSystem: BuildSystemProvider.Kind, @@ -548,7 +563,8 @@ struct TestCommandTests { ), .issue("https://github.com/swiftlang/swift-package-manager/issues/8479", relationship: .defect), .SWBINTTODO("Result XML could not be found. The build fails because of missing test helper generation logic for non-macOS platforms"), - arguments: SupportedBuildSystemOnAllPlatforms.filter { $0 != .xcode }, BuildConfiguration.allCases.map { config in + arguments: SupportedBuildSystemOnAllPlatforms.filter { $0 != .xcode }, + BuildConfiguration.allCases.map { config in [ ( fixtureName: "Miscellaneous/TestSingleFailureXCTest", @@ -657,7 +673,7 @@ struct TestCommandTests { ], configuration: config, id: "Multiple Swift Testing Tests Failure Message With Flag Disabled", - ) + ), ] }.flatMap { $0 } ) @@ -668,7 +684,7 @@ struct TestCommandTests { // windows issue not recorded for: // - native, single, XCTest, experimental true // - native, single, XCTest, experimental false - try await withKnownIssue( isIntermittent: (ProcessInfo.hostOperatingSystem == .windows)) { + try await withKnownIssue(isIntermittent: (ProcessInfo.hostOperatingSystem == .windows)) { try await fixture(name: tcdata.fixtureName) { fixturePath in // GIVEN we have a Package with a failing \(testRunner) test cases let xUnitOutput = fixturePath.appending("result.xml") @@ -711,13 +727,14 @@ struct TestCommandTests { } @Test( - .tags( + .tags( .Feature.TargetType.Executable, .Feature.CommandLineArguments.TestFilter, ), .issue("https://github.com/swiftlang/swift-package-manager/issues/8479", relationship: .defect), .SWBINTTODO("Result XML could not be found. The build fails because of missing test helper generation logic for non-macOS platforms"), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func swiftTestFilter( buildSystem: BuildSystemProvider.Kind, @@ -763,7 +780,8 @@ struct TestCommandTests { ), .issue("https://github.com/swiftlang/swift-package-manager/issues/8479", relationship: .defect), .SWBINTTODO("Result XML could not be found. The build fails because of missing test helper generation logic for non-macOS platforms"), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func swiftTestSkip( buildSystem: BuildSystemProvider.Kind, @@ -838,7 +856,8 @@ struct TestCommandTests { ), .SWBINTTODO("Fails to find test executable"), .issue("https://github.com/swiftlang/swift-package-manager/pull/8722", relationship: .fixedBy), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func enableTestDiscoveryDeprecation( buildSystem: BuildSystemProvider.Kind, @@ -888,7 +907,8 @@ struct TestCommandTests { .tags( Tag.Feature.Command.Build, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func listWithoutBuildingFirst( buildSystem: BuildSystemProvider.Kind, @@ -926,7 +946,8 @@ struct TestCommandTests { .tags( Tag.Feature.Command.Build, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func listBuildFirstThenList( buildSystem: BuildSystemProvider.Kind, @@ -944,13 +965,13 @@ struct TestCommandTests { ) #expect(buildStdout.contains("Build complete!")) } when: { - (buildSystem == .native && configuration == .release) // error: module 'Simple' was not compiled for testing - || (configuration == .release && buildSystem != .native && ProcessInfo.hostOperatingSystem != .windows) // (configuration == .release) - || (buildSystem != .native && ProcessInfo.hostOperatingSystem == .windows) // || (ProcessInfo.hostOperatingSystem == .windows) + (buildSystem == .native && configuration == .release) // error: module 'Simple' was not compiled for testing + || (configuration == .release && buildSystem != .native && ProcessInfo.hostOperatingSystem != .windows) // (configuration == .release) + || (buildSystem != .native && ProcessInfo.hostOperatingSystem == .windows) // || (ProcessInfo.hostOperatingSystem == .windows) } // list - try await withKnownIssue("Fails to find test executable", isIntermittent: ([.linux, .windows].contains(ProcessInfo.hostOperatingSystem))) { // windows; issue not recorded + try await withKnownIssue("Fails to find test executable", isIntermittent: ([.linux, .windows].contains(ProcessInfo.hostOperatingSystem))) { // windows; issue not recorded let (listStdout, listStderr) = try await execute( ["list"], packagePath: fixturePath, @@ -965,8 +986,8 @@ struct TestCommandTests { #expect(listStdout.contains("SimpleTests.SimpleTests/testThrowing")) } when: { (configuration == .release && ProcessInfo.hostOperatingSystem != .macOS) - || (buildSystem == .swiftbuild && [.linux].contains(ProcessInfo.hostOperatingSystem)) - || (buildSystem == .swiftbuild && [.windows].contains(ProcessInfo.hostOperatingSystem)) && configuration == .debug + || (buildSystem == .swiftbuild && [.linux].contains(ProcessInfo.hostOperatingSystem)) + || (buildSystem == .swiftbuild && [.windows].contains(ProcessInfo.hostOperatingSystem)) && configuration == .debug } } } @@ -981,7 +1002,8 @@ struct TestCommandTests { .tags( Tag.Feature.Command.Build, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func listBuildFirstThenListWhileSkippingBuild( buildSystem: BuildSystemProvider.Kind, @@ -990,7 +1012,7 @@ struct TestCommandTests { try await withKnownIssue("Failes to find test executable") { try await fixture(name: "Miscellaneous/TestDiscovery/Simple") { fixturePath in // build first - try await withKnownIssue("Failed to save attachment", isIntermittent: (.windows == ProcessInfo.hostOperatingSystem)) { // windows: native, debug did not record issue + try await withKnownIssue("Failed to save attachment", isIntermittent: (.windows == ProcessInfo.hostOperatingSystem)) { // windows: native, debug did not record issue // This might be intermittently failing on windows let (buildStdout, _) = try await executeSwiftBuild( fixturePath, @@ -1022,12 +1044,13 @@ struct TestCommandTests { } } when: { (configuration == .release) - || (buildSystem == .swiftbuild && .linux == ProcessInfo.hostOperatingSystem && configuration == .release) + || (buildSystem == .swiftbuild && .linux == ProcessInfo.hostOperatingSystem && configuration == .release) } } @Test( - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func listWithSkipBuildAndNoBuildArtifacts( buildSystem: BuildSystemProvider.Kind, @@ -1059,7 +1082,8 @@ struct TestCommandTests { .Feature.TargetType.Executable, .Feature.CommandLineArguments.TestEnableSwiftTesting, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func basicSwiftTestingIntegration( buildSystem: BuildSystemProvider.Kind, @@ -1089,7 +1113,8 @@ struct TestCommandTests { ), .skipHostOS(.macOS), // because this was guarded with `#if !canImport(Darwin)` .SWBINTTODO("This is a PIF builder missing GUID problem. Further investigation is needed."), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func generatedMainIsConcurrencySafe_XCTest( buildSystem: BuildSystemProvider.Kind, @@ -1111,12 +1136,13 @@ struct TestCommandTests { } } @Test( - .tags( + .tags( .Feature.TargetType.Executable, ), .skipHostOS(.macOS), // because this was guarded with `#if !canImport(Darwin)` .SWBINTTODO("This is a PIF builder missing GUID problem. Further investigation is needed."), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func generatedMainIsExistentialAnyClean( buildSystem: BuildSystemProvider.Kind, @@ -1139,12 +1165,13 @@ struct TestCommandTests { } @Test( - .tags( + .tags( .Feature.TargetType.Executable, ), .IssueWindowsPathTestsFailures, .issue("https://github.com/swiftlang/swift-package-manager/issues/8602", relationship: .defect), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func libraryEnvironmentVariable( buildSystem: BuildSystemProvider.Kind, @@ -1177,7 +1204,8 @@ struct TestCommandTests { ), .SWBINTTODO("Fails to find test executable"), .issue("https://github.com/swiftlang/swift-package-manager/pull/8722", relationship: .fixedBy), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func XCTestOnlyDoesNotLogAboutNoMatchingTests( buildSystem: BuildSystemProvider.Kind, @@ -1204,7 +1232,8 @@ struct TestCommandTests { ), .issue("https://github.com/swiftlang/swift-package-manager/issues/6605", relationship: .verifies), .issue("https://github.com/swiftlang/swift-package-manager/issues/8602", relationship: .defect), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func fatalErrorDisplayedCorrectNumberOfTimesWhenSingleXCTestHasFatalErrorInBuildCompilation( buildSystem: BuildSystemProvider.Kind, diff --git a/Tests/ExtraTests/Package.swift b/Tests/ExtraTests/Package.swift index 8787b6da66d..350ce1efedc 100644 --- a/Tests/ExtraTests/Package.swift +++ b/Tests/ExtraTests/Package.swift @@ -5,11 +5,12 @@ import PackageDescription let package = Package( name: "ExtraTests", dependencies: [ - .package(path: "../../"), + .package(path: "../../") ], targets: [ .testTarget( name: "ExtraTests", - dependencies: ["SPMUtility"]), + dependencies: ["SPMUtility"] + ) ] ) diff --git a/Tests/FunctionalTests/DependencyResolutionTests.swift b/Tests/FunctionalTests/DependencyResolutionTests.swift index 887a3adbcb6..aaa71c49b86 100644 --- a/Tests/FunctionalTests/DependencyResolutionTests.swift +++ b/Tests/FunctionalTests/DependencyResolutionTests.swift @@ -43,7 +43,7 @@ struct DependencyResolutionTests { buildSystem: BuildSystemProvider.Kind, configuration: BuildConfiguration, ) async throws { - try await withKnownIssue(isIntermittent: (ProcessInfo.hostOperatingSystem == .windows) ) { + try await withKnownIssue(isIntermittent: (ProcessInfo.hostOperatingSystem == .windows)) { try await fixture(name: "DependencyResolution/Internal/Simple") { fixturePath in try await executeSwiftBuild( fixturePath, @@ -57,7 +57,7 @@ struct DependencyResolutionTests { #expect(output == "Foo\nBar\n") } } when: { - (ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild) + (ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild) } } @@ -83,7 +83,7 @@ struct DependencyResolutionTests { ) } } when: { - configuration == .release && buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem != .windows // an error is not raised. + configuration == .release && buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem != .windows // an error is not raised. } } } @@ -177,8 +177,8 @@ struct DependencyResolutionTests { ) async throws { try await withKnownIssue( isIntermittent: ProcessInfo.hostOperatingSystem == .windows - // rdar://162339964 - || (ProcessInfo.isHostAmazonLinux2() && buildSystem == .swiftbuild) + // rdar://162339964 + || (ProcessInfo.isHostAmazonLinux2() && buildSystem == .swiftbuild) ) { try await fixture(name: "DependencyResolution/External/Complex") { fixturePath in let packageRoot = fixturePath.appending("app") @@ -195,8 +195,8 @@ struct DependencyResolutionTests { #expect(output == "♣︎K\n♣︎Q\n♣︎J\n♣︎10\n♣︎9\n♣︎8\n♣︎7\n♣︎6\n♣︎5\n♣︎4\n") } } when: { - ProcessInfo.hostOperatingSystem == .windows // due to long path issues - || (ProcessInfo.isHostAmazonLinux2() && buildSystem == .swiftbuild) // Linker ld throws an unexpected error. + ProcessInfo.hostOperatingSystem == .windows // due to long path issues + || (ProcessInfo.isHostAmazonLinux2() && buildSystem == .swiftbuild) // Linker ld throws an unexpected error. } } diff --git a/Tests/FunctionalTests/LibraryEvolutionXCFLinuxTests.swift b/Tests/FunctionalTests/LibraryEvolutionXCFLinuxTests.swift index b441c1a83f9..a8e2a9fa51e 100644 --- a/Tests/FunctionalTests/LibraryEvolutionXCFLinuxTests.swift +++ b/Tests/FunctionalTests/LibraryEvolutionXCFLinuxTests.swift @@ -32,9 +32,9 @@ private struct SwiftPMTests { ) #if arch(arm64) - let arch = "aarch64" + let arch = "aarch64" #elseif arch(x86_64) - let arch = "x86_64" + let arch = "x86_64" #endif let platform = "linux" @@ -62,41 +62,42 @@ private struct SwiftPMTests { try localFileSystem.writeFileContents( xcframeworkPath.appending(component: "Info.plist"), string: """ - - - - - AvailableLibraries - - - BinaryPath - \(libraryName) - LibraryIdentifier - \(platform)-\(arch) - LibraryPath - \(libraryName) - SupportedArchitectures - - \(arch) - - SupportedPlatform - \(platform) - - - CFBundlePackageType - XFWK - XCFrameworkFormatVersion - 1.0 - - - """ + + + + + AvailableLibraries + + + BinaryPath + \(libraryName) + LibraryIdentifier + \(platform)-\(arch) + LibraryPath + \(libraryName) + SupportedArchitectures + + \(arch) + + SupportedPlatform + \(platform) + + + CFBundlePackageType + XFWK + XCFrameworkFormatVersion + 1.0 + + + """ ) } let packagePath = fixturePath.appending(component: "TestBinary") let scratchPath = packagePath.appending(component: ".build-test") let runOutput = try await executeSwiftRun( - packagePath, "TestBinary", + packagePath, + "TestBinary", extraArgs: [ "--scratch-path", scratchPath.pathString, "--experimental-xcframeworks-on-linux", ], diff --git a/Tests/FunctionalTests/MacroTests.swift b/Tests/FunctionalTests/MacroTests.swift index 1526ca3e40c..b1fafb4a398 100644 --- a/Tests/FunctionalTests/MacroTests.swift +++ b/Tests/FunctionalTests/MacroTests.swift @@ -32,7 +32,8 @@ struct MacroTests { .tags( Tag.Feature.Command.Build ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func macrosBasic( buildSystem: BuildSystemProvider.Kind, diff --git a/Tests/FunctionalTests/MiscellaneousTests.swift b/Tests/FunctionalTests/MiscellaneousTests.swift index f10c6b65872..dcc7396fda7 100644 --- a/Tests/FunctionalTests/MiscellaneousTests.swift +++ b/Tests/FunctionalTests/MiscellaneousTests.swift @@ -36,11 +36,21 @@ final class MiscellaneousTestCase: XCTestCase { XCTAssertMatch(stderr, .regex("Computed .* at 1\\.2\\.3")) // in "swift build" build output goes to stdout XCTAssertMatch(stdout, .contains("Compiling Foo Foo.swift")) - XCTAssertMatch(stdout, .or(.contains("Merging module Foo"), - .contains("Emitting module Foo"))) + XCTAssertMatch( + stdout, + .or( + .contains("Merging module Foo"), + .contains("Emitting module Foo") + ) + ) XCTAssertMatch(stdout, .contains("Compiling Bar main.swift")) - XCTAssertMatch(stdout, .or(.contains("Merging module Bar"), - .contains("Emitting module Bar"))) + XCTAssertMatch( + stdout, + .or( + .contains("Merging module Bar"), + .contains("Emitting module Bar") + ) + ) XCTAssertMatch(stdout, .contains("Linking Bar")) XCTAssertMatch(stdout, .contains("Build complete!")) } @@ -239,26 +249,26 @@ final class MiscellaneousTestCase: XCTestCase { func testSecondBuildIsNullInModulemapGen() throws { // This has been failing on the Swift CI sometimes, need to investigate. - #if false - // Make sure that swiftpm doesn't rebuild second time if the modulemap is being generated. - try fixtureXCTest(name: "CFamilyTargets/SwiftCMixed") { fixturePath in - var output = try await executeSwiftBuild( - prefix, - buildSystem: .native, - ) - XCTAssertFalse(output.isEmpty, output) - output = try await executeSwiftBuild( - prefix, - buildSystem: .native, - ) - XCTAssertTrue(output.isEmpty, output) - } - #endif + #if false + // Make sure that swiftpm doesn't rebuild second time if the modulemap is being generated. + try fixtureXCTest(name: "CFamilyTargets/SwiftCMixed") { fixturePath in + var output = try await executeSwiftBuild( + prefix, + buildSystem: .native, + ) + XCTAssertFalse(output.isEmpty, output) + output = try await executeSwiftBuild( + prefix, + buildSystem: .native, + ) + XCTAssertTrue(output.isEmpty, output) + } + #endif } func testOverridingDeploymentTargetUsingSwiftCompilerArgument() async throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif try await fixtureXCTest(name: "Miscellaneous/DistantFutureDeploymentTarget") { fixturePath in let hostTriple = try UserToolchain.default.targetTriple @@ -282,19 +292,21 @@ final class MiscellaneousTestCase: XCTestCase { let pcFile = fixturePath.appending("libSystemModule.pc") - try localFileSystem.writeFileContents(pcFile, string: """ - prefix=\(systemModule.pathString) - exec_prefix=${prefix} - libdir=${exec_prefix} - includedir=${prefix}/Sources/include - Name: SystemModule - URL: http://127.0.0.1/ - Description: The one and only SystemModule - Version: 1.10.0 - Cflags: -I${includedir} - Libs: -L${libdir} -lSystemModule + try localFileSystem.writeFileContents( + pcFile, + string: """ + prefix=\(systemModule.pathString) + exec_prefix=${prefix} + libdir=${exec_prefix} + includedir=${prefix}/Sources/include + Name: SystemModule + URL: http://127.0.0.1/ + Description: The one and only SystemModule + Version: 1.10.0 + Cflags: -I${includedir} + Libs: -L${libdir} -lSystemModule - """ + """ ) let moduleUser = fixturePath.appending("SystemModuleUserClang") @@ -328,54 +340,56 @@ final class MiscellaneousTestCase: XCTestCase { func testCanKillSubprocessOnSigInt() throws { // swift-pm: Spurious? failures of MiscellaneousTestCase.testCanKillSubprocessOnSigInt on linux #if false - try fixtureXCTest(name: "DependencyResolution/External/Simple") { fixturePath in - - let fakeGit = fixturePath.appending(components: "bin", "git") - let waitFile = fixturePath.appending(components: "waitfile") + try fixtureXCTest(name: "DependencyResolution/External/Simple") { fixturePath in + + let fakeGit = fixturePath.appending(components: "bin", "git") + let waitFile = fixturePath.appending(components: "waitfile") + + try localFileSystem.createDirectory(fakeGit.parentDirectory) + + // Write out fake git. + try localFileSystem.writeFileContents( + fakeGit, + string: + """ + #!/bin/sh + set -e + printf "$$" >> \(waitFile) + while true; do sleep 1; done + """ + ) - try localFileSystem.createDirectory(fakeGit.parentDirectory) + // Make it executable. + _ = try AsyncProcess.popen(args: "chmod", "+x", fakeGit.description) - // Write out fake git. - try localFileSystem.writeFileContents(fakeGit, string: - """ - #!/bin/sh - set -e - printf "$$" >> \(waitFile) - while true; do sleep 1; done - """ - ) + // Put fake git in PATH. + var env = ProcessInfo.processInfo.environment + let oldPath = env["PATH"] + env["PATH"] = fakeGit.parentDirectory.description + if let oldPath { + env["PATH"] = env["PATH"]! + ":" + oldPath + } - // Make it executable. - _ = try AsyncProcess.popen(args: "chmod", "+x", fakeGit.description) + // Launch swift-build. + let app = fixturePath.appending("Bar") + let process = AsyncProcess(args: SwiftPM.Build.path.pathString, "--package-path", app.pathString, environment: env) + try process.launch() - // Put fake git in PATH. - var env = ProcessInfo.processInfo.environment - let oldPath = env["PATH"] - env["PATH"] = fakeGit.parentDirectory.description - if let oldPath { - env["PATH"] = env["PATH"]! + ":" + oldPath - } + guard waitForFile(waitFile) else { + return XCTFail("Couldn't launch the process") + } + // Interrupt the process. + process.signal(SIGINT) + let result = try process.waitUntilExit() - // Launch swift-build. - let app = fixturePath.appending("Bar") - let process = AsyncProcess(args: SwiftPM.Build.path.pathString, "--package-path", app.pathString, environment: env) - try process.launch() + // We should not have exited with zero. + XCTAssert(result.exitStatus != .terminated(code: 0)) - guard waitForFile(waitFile) else { - return XCTFail("Couldn't launch the process") + // Process and subprocesses should be dead. + let contents: String = try localFileSystem.readFileContents(waitFile) + XCTAssertFalse(try AsyncProcess.running(process.processID)) + XCTAssertFalse(try AsyncProcess.running(ProcessID(contents)!)) } - // Interrupt the process. - process.signal(SIGINT) - let result = try process.waitUntilExit() - - // We should not have exited with zero. - XCTAssert(result.exitStatus != .terminated(code: 0)) - - // Process and subprocesses should be dead. - let contents: String = try localFileSystem.readFileContents(waitFile) - XCTAssertFalse(try AsyncProcess.running(process.processID)) - XCTAssertFalse(try AsyncProcess.running(ProcessID(contents)!)) - } #endif } @@ -424,70 +438,72 @@ final class MiscellaneousTestCase: XCTestCase { func testLTO() async throws { throw XCTSkip("No longer works with newer toolchains") #if os(macOS) - // FIXME: this test requires swift-driver to be installed - // Currently swift-ci does not build/install swift-driver before running - // swift-package-manager tests which results in this test failing. - // See the following additional discussion: - // - https://github.com/swiftlang/swift/pull/69696 - // - https://github.com/swiftlang/swift/pull/61766 - // - https://github.com/swiftlang/swift-package-manager/pull/5842#issuecomment-1301632685 - try await fixtureXCTest(name: "Miscellaneous/LTO/SwiftAndCTargets") { fixturePath in - /*let output =*/ - try await executeSwiftBuild( - fixturePath, - extraArgs: ["--experimental-lto-mode=full", "--verbose"], - buildSystem: .native, - - ) - // FIXME: On macOS dsymutil cannot find temporary .o files? (#6890) - // Ensure warnings like the following are not present in build output - // warning: (arm64) /var/folders/ym/6l_0x8vj0b70sz_4h9d70p440000gn/T/main-e120de.o unable to open object file: No such file or directory - // XCTAssertNoMatch(output.stdout, .contains("unable to open object file")) - } + // FIXME: this test requires swift-driver to be installed + // Currently swift-ci does not build/install swift-driver before running + // swift-package-manager tests which results in this test failing. + // See the following additional discussion: + // - https://github.com/swiftlang/swift/pull/69696 + // - https://github.com/swiftlang/swift/pull/61766 + // - https://github.com/swiftlang/swift-package-manager/pull/5842#issuecomment-1301632685 + try await fixtureXCTest(name: "Miscellaneous/LTO/SwiftAndCTargets") { fixturePath in + /*let output =*/ + try await executeSwiftBuild( + fixturePath, + extraArgs: ["--experimental-lto-mode=full", "--verbose"], + buildSystem: .native, + + ) + // FIXME: On macOS dsymutil cannot find temporary .o files? (#6890) + // Ensure warnings like the following are not present in build output + // warning: (arm64) /var/folders/ym/6l_0x8vj0b70sz_4h9d70p440000gn/T/main-e120de.o unable to open object file: No such file or directory + // XCTAssertNoMatch(output.stdout, .contains("unable to open object file")) + } #endif } func testUnicode() async throws { try XCTSkipOnWindows(because: "Filepath too long error") - #if !os(Linux) && !os(Android) // TODO: - Linux has trouble with this and needs investigation. - try await fixtureXCTest(name: "Miscellaneous/Unicode") { fixturePath in - // See the fixture manifest for an explanation of this string. - let complicatedString = "πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄" - let verify = "\u{03C0}\u{0FB2C}\u{00B5}\u{1D11E}\u{1F1FA}\u{1F1F3}\u{1F1EE}\u{1F1F1}\u{0078}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}" - XCTAssert( - complicatedString.unicodeScalars.elementsEqual(verify.unicodeScalars), - "\(complicatedString) ≠ \(verify)") - - // ••••• Set up dependency. - let dependencyName = "UnicodeDependency‐\(complicatedString)" - let dependencyOrigin = AbsolutePath(#file).parentDirectory.parentDirectory.parentDirectory - .appending("Fixtures") - .appending("Miscellaneous") - .appending(component: dependencyName) - let dependencyDestination = fixturePath.parentDirectory.appending(component: dependencyName) - try? FileManager.default.removeItem(atPath: dependencyDestination.pathString) - defer { try? FileManager.default.removeItem(atPath: dependencyDestination.pathString) } - try FileManager.default.copyItem( - atPath: dependencyOrigin.pathString, - toPath: dependencyDestination.pathString) - let dependency = GitRepository(path: dependencyDestination) - try dependency.create() - try dependency.stageEverything() - try dependency.commit() - try dependency.tag(name: "1.0.0") - // ••••• - - // Attempt several operations. - try await executeSwiftTest( - fixturePath, - buildSystem: .native, - ) - try await executeSwiftRun( - fixturePath, - complicatedString + "‐tool", - buildSystem: .native, - ) - } + #if !os(Linux) && !os(Android) // TODO: - Linux has trouble with this and needs investigation. + try await fixtureXCTest(name: "Miscellaneous/Unicode") { fixturePath in + // See the fixture manifest for an explanation of this string. + let complicatedString = "πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄" + let verify = "\u{03C0}\u{0FB2C}\u{00B5}\u{1D11E}\u{1F1FA}\u{1F1F3}\u{1F1EE}\u{1F1F1}\u{0078}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}" + XCTAssert( + complicatedString.unicodeScalars.elementsEqual(verify.unicodeScalars), + "\(complicatedString) ≠ \(verify)" + ) + + // ••••• Set up dependency. + let dependencyName = "UnicodeDependency‐\(complicatedString)" + let dependencyOrigin = AbsolutePath(#file).parentDirectory.parentDirectory.parentDirectory + .appending("Fixtures") + .appending("Miscellaneous") + .appending(component: dependencyName) + let dependencyDestination = fixturePath.parentDirectory.appending(component: dependencyName) + try? FileManager.default.removeItem(atPath: dependencyDestination.pathString) + defer { try? FileManager.default.removeItem(atPath: dependencyDestination.pathString) } + try FileManager.default.copyItem( + atPath: dependencyOrigin.pathString, + toPath: dependencyDestination.pathString + ) + let dependency = GitRepository(path: dependencyDestination) + try dependency.create() + try dependency.stageEverything() + try dependency.commit() + try dependency.tag(name: "1.0.0") + // ••••• + + // Attempt several operations. + try await executeSwiftTest( + fixturePath, + buildSystem: .native, + ) + try await executeSwiftRun( + fixturePath, + complicatedString + "‐tool", + buildSystem: .native, + ) + } #endif } @@ -509,21 +525,21 @@ final class MiscellaneousTestCase: XCTestCase { XCTAssertMatch(stdout, .contains("Hello, planet")) } catch { #if os(macOS) && arch(arm64) - // Add some logging but ignore the failure for an environment being investigated. - let (stdout, stderr) = try await executeSwiftTest( - fixturePath, - extraArgs: ["-v"], - buildSystem: .native, - ) - print("testTestsCanLinkAgainstExecutable failed") - print("ENV:\n") - for (k, v) in Environment.current.sorted(by: { $0.key < $1.key }) { - print(" \(k)=\(v)") - } - print("STDOUT:\n\(stdout)") - print("STDERR:\n\(stderr)") + // Add some logging but ignore the failure for an environment being investigated. + let (stdout, stderr) = try await executeSwiftTest( + fixturePath, + extraArgs: ["-v"], + buildSystem: .native, + ) + print("testTestsCanLinkAgainstExecutable failed") + print("ENV:\n") + for (k, v) in Environment.current.sorted(by: { $0.key < $1.key }) { + print(" \(k)=\(v)") + } + print("STDOUT:\n\(stdout)") + print("STDERR:\n\(stderr)") #else - XCTFail("\(error)") + XCTFail("\(error)") #endif } } @@ -588,9 +604,9 @@ final class MiscellaneousTestCase: XCTestCase { func testEditModeEndToEnd() async throws { try await fixtureXCTest(name: "Miscellaneous/Edit") { fixturePath in #if os(Windows) - let prefix = fixturePath + let prefix = fixturePath #else - let prefix = try resolveSymlinks(fixturePath) + let prefix = try resolveSymlinks(fixturePath) #endif let appPath = fixturePath.appending("App") @@ -672,24 +688,24 @@ final class MiscellaneousTestCase: XCTestCase { // `FileSystem` does not support `chmod` on Linux #if os(macOS) - try await fixtureXCTest(name: "Miscellaneous/Simple") { path in - try localFileSystem.chmod(.userUnWritable, path: path) - let customCachePath = path.appending(components: "custom", "cache") - XCTAssertNoSuchPath(customCachePath) - await XCTAssertAsyncThrowsError( - try await executeSwiftBuild( - path, - extraArgs: ["--cache-path", customCachePath.pathString], - buildSystem: .native, - ) - ) { error in - guard case SwiftPMError.executionFailure(_, _, let stderr) = error else { - return XCTFail("invalid error \(error)") + try await fixtureXCTest(name: "Miscellaneous/Simple") { path in + try localFileSystem.chmod(.userUnWritable, path: path) + let customCachePath = path.appending(components: "custom", "cache") + XCTAssertNoSuchPath(customCachePath) + await XCTAssertAsyncThrowsError( + try await executeSwiftBuild( + path, + extraArgs: ["--cache-path", customCachePath.pathString], + buildSystem: .native, + ) + ) { error in + guard case SwiftPMError.executionFailure(_, _, let stderr) = error else { + return XCTFail("invalid error \(error)") + } + XCTAssert(stderr.contains("error: invalid access to "), "expected permissions error. stderr: '\(stderr)'") } - XCTAssert(stderr.contains("error: invalid access to "), "expected permissions error. stderr: '\(stderr)'") + XCTAssertNoSuchPath(customCachePath) } - XCTAssertNoSuchPath(customCachePath) - } #endif } @@ -707,24 +723,24 @@ final class MiscellaneousTestCase: XCTestCase { // `FileSystem` does not support `chmod` on Linux #if os(macOS) - try await fixtureXCTest(name: "Miscellaneous/Simple") { path in - try localFileSystem.chmod(.userUnWritable, path: path) - let customConfigPath = path.appending(components: "custom", "config") - XCTAssertNoSuchPath(customConfigPath) - await XCTAssertAsyncThrowsError( - try await executeSwiftBuild( - path, - extraArgs: ["--config-path", customConfigPath.pathString], - buildSystem: .native, - ) - ) { error in - guard case SwiftPMError.executionFailure(_, _, let stderr) = error else { - return XCTFail("invalid error \(error)") + try await fixtureXCTest(name: "Miscellaneous/Simple") { path in + try localFileSystem.chmod(.userUnWritable, path: path) + let customConfigPath = path.appending(components: "custom", "config") + XCTAssertNoSuchPath(customConfigPath) + await XCTAssertAsyncThrowsError( + try await executeSwiftBuild( + path, + extraArgs: ["--config-path", customConfigPath.pathString], + buildSystem: .native, + ) + ) { error in + guard case SwiftPMError.executionFailure(_, _, let stderr) = error else { + return XCTFail("invalid error \(error)") + } + XCTAssert(stderr.contains("error: invalid access to "), "expected permissions error. stderr: '\(stderr)'") } - XCTAssert(stderr.contains("error: invalid access to "), "expected permissions error. stderr: '\(stderr)'") + XCTAssertNoSuchPath(customConfigPath) } - XCTAssertNoSuchPath(customConfigPath) - } #endif } @@ -742,23 +758,23 @@ final class MiscellaneousTestCase: XCTestCase { // `FileSystem` does not support `chmod` on Linux #if os(macOS) - try await fixtureXCTest(name: "Miscellaneous/Simple") { path in - try localFileSystem.chmod(.userUnWritable, path: path) - let customSecurityPath = path.appending(components: "custom", "security") - XCTAssertNoSuchPath(customSecurityPath) - await XCTAssertAsyncThrowsError( - try await executeSwiftBuild( - path, - extraArgs: ["--security-path", customSecurityPath.pathString], - buildSystem: .native, - ) - ) { error in - guard case SwiftPMError.executionFailure(_, _, let stderr) = error else { - return XCTFail("invalid error \(error)") + try await fixtureXCTest(name: "Miscellaneous/Simple") { path in + try localFileSystem.chmod(.userUnWritable, path: path) + let customSecurityPath = path.appending(components: "custom", "security") + XCTAssertNoSuchPath(customSecurityPath) + await XCTAssertAsyncThrowsError( + try await executeSwiftBuild( + path, + extraArgs: ["--security-path", customSecurityPath.pathString], + buildSystem: .native, + ) + ) { error in + guard case SwiftPMError.executionFailure(_, _, let stderr) = error else { + return XCTFail("invalid error \(error)") + } + XCTAssert(stderr.contains("error: invalid access to "), "expected permissions error. stderr: '\(stderr)'") } - XCTAssert(stderr.contains("error: invalid access to "), "expected permissions error. stderr: '\(stderr)'") } - } #endif } @@ -767,8 +783,8 @@ final class MiscellaneousTestCase: XCTestCase { try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try XCTSkipOnWindows( because: """ - Invalid path. Possibly related to https://github.com/swiftlang/swift-package-manager/issues/8511 or https://github.com/swiftlang/swift-package-manager/issues/8602 - """, + Invalid path. Possibly related to https://github.com/swiftlang/swift-package-manager/issues/8511 or https://github.com/swiftlang/swift-package-manager/issues/8602 + """, skipPlatformCi: true, ) @@ -802,7 +818,7 @@ final class MiscellaneousTestCase: XCTestCase { XCTAssertDirectoryExists(package.appending(".build")) XCTAssertNoMatch(stdout1, .contains("command_arguments")) XCTAssertNoMatch(stderr1, .contains("command_arguments")) - + // Now test, make sure we got the `.build` directory where we expect it, and that there is no JSON output (by looking for known output). let (stdout2, stderr2) = try await executeSwiftTest( package, @@ -858,27 +874,27 @@ final class MiscellaneousTestCase: XCTestCase { try await fixtureXCTest(name: "Miscellaneous/RootPackageWithConditionals") { path in let (_, stderr) = try await executeSwiftBuild( path, - env: ["SWIFT_DRIVER_SWIFTSCAN_LIB" : "/this/is/a/bad/path"], + env: ["SWIFT_DRIVER_SWIFTSCAN_LIB": "/this/is/a/bad/path"], buildSystem: .native, ) let errors = stderr.components(separatedBy: .newlines).filter { !$0.contains("[logging] misuse") && !$0.isEmpty } - .filter { !$0.contains("Unable to locate libSwiftScan") } + .filter { !$0.contains("Unable to locate libSwiftScan") } XCTAssertEqual(errors, [], "unexpected errors: \(errors)") } } func testRootPackageWithConditionalsSwiftBuild() async throws { try XCTSkipOnWindows(because: "produces a filename that is too long, needs investigation") -#if os(Linux) - if FileManager.default.contents(atPath: "/etc/system-release").map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false { - throw XCTSkip("Skipping Swift Build testing on Amazon Linux because of platform issues.") - } -#endif + #if os(Linux) + if FileManager.default.contents(atPath: "/etc/system-release").map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false { + throw XCTSkip("Skipping Swift Build testing on Amazon Linux because of platform issues.") + } + #endif try await fixtureXCTest(name: "Miscellaneous/RootPackageWithConditionals") { path in _ = try await executeSwiftBuild( path, extraArgs: ["--build-system=swiftbuild"], - env: ["SWIFT_DRIVER_SWIFTSCAN_LIB" : "/this/is/a/bad/path"], + env: ["SWIFT_DRIVER_SWIFTSCAN_LIB": "/this/is/a/bad/path"], buildSystem: .native, ) } diff --git a/Tests/FunctionalTests/ModuleAliasingFixtureTests.swift b/Tests/FunctionalTests/ModuleAliasingFixtureTests.swift index e2af71c7758..5ebf98474de 100644 --- a/Tests/FunctionalTests/ModuleAliasingFixtureTests.swift +++ b/Tests/FunctionalTests/ModuleAliasingFixtureTests.swift @@ -144,41 +144,41 @@ struct ModuleAliasingFixtureTests { let buildSystem = data.buildSystem let configuration = data.config try await withKnownIssue(isIntermittent: true) { - try await fixture(name: "ModuleAliasing/NestedDeps1") { fixturePath in - let pkgPath = fixturePath.appending(components: "AppPkg") - let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration)) - let expectedModules = [ - "A.swiftmodule", - "AFooUtils.swiftmodule", - "CarUtils.swiftmodule", - "X.swiftmodule", - "XFooUtils.swiftmodule", - "XUtils.swiftmodule", - ] - try await executeSwiftBuild( - pkgPath, - configuration: configuration, - extraArgs: ["--vv"], - buildSystem: buildSystem, - ) - expectFileExists(at: buildPath.appending(components: executableName("App"))) - for file in expectedModules { - switch buildSystem { - case .native: - expectFileExists(at: buildPath.appending(components: "Modules", file)) - case .swiftbuild: - expectFileExists(at: buildPath.appending(components: file)) - case .xcode: - Issue.record("expectations are not implemented") + try await fixture(name: "ModuleAliasing/NestedDeps1") { fixturePath in + let pkgPath = fixturePath.appending(components: "AppPkg") + let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration)) + let expectedModules = [ + "A.swiftmodule", + "AFooUtils.swiftmodule", + "CarUtils.swiftmodule", + "X.swiftmodule", + "XFooUtils.swiftmodule", + "XUtils.swiftmodule", + ] + try await executeSwiftBuild( + pkgPath, + configuration: configuration, + extraArgs: ["--vv"], + buildSystem: buildSystem, + ) + expectFileExists(at: buildPath.appending(components: executableName("App"))) + for file in expectedModules { + switch buildSystem { + case .native: + expectFileExists(at: buildPath.appending(components: "Modules", file)) + case .swiftbuild: + expectFileExists(at: buildPath.appending(components: file)) + case .xcode: + Issue.record("expectations are not implemented") + } } - } - _ = try await executeSwiftBuild( - pkgPath, - configuration: configuration, - buildSystem: buildSystem, - ) - } + _ = try await executeSwiftBuild( + pkgPath, + configuration: configuration, + buildSystem: buildSystem, + ) + } } when: { ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild } @@ -200,38 +200,38 @@ struct ModuleAliasingFixtureTests { let buildSystem = data.buildSystem let configuration = data.config try await withKnownIssue(isIntermittent: true) { - try await fixture(name: "ModuleAliasing/NestedDeps2") { fixturePath in - let pkgPath = fixturePath.appending(components: "AppPkg") - let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration)) - try await executeSwiftBuild( - pkgPath, - configuration: configuration, - extraArgs: ["--vv"], - buildSystem: buildSystem, - ) - let expectedModules = [ - "A.swiftmodule", - "BUtils.swiftmodule", - "CUtils.swiftmodule", - "XUtils.swiftmodule", - ] - expectFileExists(at: buildPath.appending(components: executableName("App"))) - for file in expectedModules { - switch buildSystem { - case .native: - expectFileExists(at: buildPath.appending(components: "Modules", file)) - case .swiftbuild: - expectFileExists(at: buildPath.appending(components: file)) - case .xcode: - Issue.record("expectations are not implemented") + try await fixture(name: "ModuleAliasing/NestedDeps2") { fixturePath in + let pkgPath = fixturePath.appending(components: "AppPkg") + let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration)) + try await executeSwiftBuild( + pkgPath, + configuration: configuration, + extraArgs: ["--vv"], + buildSystem: buildSystem, + ) + let expectedModules = [ + "A.swiftmodule", + "BUtils.swiftmodule", + "CUtils.swiftmodule", + "XUtils.swiftmodule", + ] + expectFileExists(at: buildPath.appending(components: executableName("App"))) + for file in expectedModules { + switch buildSystem { + case .native: + expectFileExists(at: buildPath.appending(components: "Modules", file)) + case .swiftbuild: + expectFileExists(at: buildPath.appending(components: file)) + case .xcode: + Issue.record("expectations are not implemented") + } } + _ = try await executeSwiftBuild( + pkgPath, + configuration: configuration, + buildSystem: buildSystem, + ) } - _ = try await executeSwiftBuild( - pkgPath, - configuration: configuration, - buildSystem: buildSystem, - ) - } } when: { ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild } diff --git a/Tests/FunctionalTests/ModuleMapTests.swift b/Tests/FunctionalTests/ModuleMapTests.swift index 94d72a6ac3a..1f50f9b2394 100644 --- a/Tests/FunctionalTests/ModuleMapTests.swift +++ b/Tests/FunctionalTests/ModuleMapTests.swift @@ -33,16 +33,16 @@ final class ModuleMapsTestCase: XCTestCase { try await AsyncProcess.checkNonZeroExit(args: executableName("clang"), "-shared", input.pathString, "-o", output.pathString) var Xld = ["-L", outdir.pathString] - #if os(Linux) || os(Android) - Xld += ["-rpath", outdir.pathString] - #endif + #if os(Linux) || os(Android) + Xld += ["-rpath", outdir.pathString] + #endif try await body(fixturePath, Xld) } } func testDirectDependency() async throws { - try XCTSkipOnWindows(because: "fails to build on windows (maybe not supported?)") + try XCTSkipOnWindows(because: "fails to build on windows (maybe not supported?)") try await fixtureXCTest(name: "ModuleMaps/Direct", cModuleName: "CFoo", rootpkg: "App") { fixturePath, Xld in await XCTAssertBuilds( fixturePath.appending("App"), @@ -71,19 +71,22 @@ final class ModuleMapsTestCase: XCTestCase { Xld: Xld, buildSystem: .native, ) - + func verify(_ conf: String) async throws { let triple = try UserToolchain.default.targetTriple let out = try await AsyncProcess.checkNonZeroExit( args: fixturePath.appending(components: "packageA", ".build", triple.platformBuildPathComponent, conf, "packageA").pathString ) - XCTAssertEqual(out, """ + XCTAssertEqual( + out, + """ calling Y.bar() Y.bar() called X.foo() called 123 - """) + """ + ) } try await verify("debug") diff --git a/Tests/FunctionalTests/PluginTests.swift b/Tests/FunctionalTests/PluginTests.swift index 2040e57a6f4..26341005aef 100644 --- a/Tests/FunctionalTests/PluginTests.swift +++ b/Tests/FunctionalTests/PluginTests.swift @@ -13,8 +13,7 @@ import Basics import _Concurrency -@_spi(SwiftPMInternal) -@testable import PackageGraph +@_spi(SwiftPMInternal) @testable import PackageGraph import PackageLoading import PackageModel @testable import SPMBuildCore @@ -94,7 +93,7 @@ struct PluginTests { } } when: { (ProcessInfo.hostOperatingSystem == .windows && CiEnvironment.runningInSelfHostedPipeline && buildSystem == .native) - || (buildSystem == .swiftbuild) + || (buildSystem == .swiftbuild) } } @@ -128,9 +127,9 @@ struct PluginTests { #expect(stdout.contains("Build of product 'MyTool' complete!"), "stdout:\n\(stdout)") case .swiftbuild: #expect(stdout.contains("Build complete!"), "stdout:\n\(stdout)") - case .xcode: + case .xcode: Issue.record("Test expectations must be defined.") - } + } } } when: { ProcessInfo.hostOperatingSystem == .windows @@ -235,7 +234,8 @@ struct PluginTests { } #expect( - stderr.contains("product 'PluginExecutable' required by package 'invaliduseofinternalpluginexecutable' target 'RootTarget' not found in package 'PluginWithInternalExecutable'."), "stderr:\n\(stderr)" + stderr.contains("product 'PluginExecutable' required by package 'invaliduseofinternalpluginexecutable' target 'RootTarget' not found in package 'PluginWithInternalExecutable'."), + "stderr:\n\(stderr)" ) } } @@ -321,12 +321,13 @@ struct PluginTests { ) async throws { try await withKnownIssue { try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let buildSpecificArgs: [String] = switch buildSystem { + let buildSpecificArgs: [String] = + switch buildSystem { case .native, .xcode: [] case .swiftbuild: ["--disable-sandbox"] - } + } let (stdout, _) = try await executeSwiftBuild( fixturePath.appending("ContrivedTestPlugin"), configuration: .debug, @@ -385,7 +386,7 @@ struct PluginTests { ) func testUseOfVendedBinaryTool(buildSystem: BuildSystemProvider.Kind) async throws { try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - try await withKnownIssue (isIntermittent: true) { + try await withKnownIssue(isIntermittent: true) { let (stdout, _) = try await executeSwiftBuild( fixturePath.appending("MyBinaryToolPlugin"), configuration: .debug, @@ -393,7 +394,7 @@ struct PluginTests { buildSystem: buildSystem, ) switch buildSystem { - case .native: + case .native: #expect(stdout.contains("Linking MyLocalTool"), "stdout:\n\(stdout)") #expect(stdout.contains("Build of product 'MyLocalTool' complete!"), "stdout:\n(stdout)") case .swiftbuild: @@ -401,7 +402,9 @@ struct PluginTests { case .xcode: Issue.record("Test has no expectation for \(buildSystem)") } - } when: { ProcessInfo.hostOperatingSystem == .windows } + } when: { + ProcessInfo.hostOperatingSystem == .windows + } } } @@ -447,14 +450,15 @@ struct PluginTests { try localFileSystem.writeFileContents( manifestFile, string: """ - // swift-tools-version: \(toolsVersion.description) - import PackageDescription - let package = Package(name: "MyPackage", - targets: [ - .target(name: "SomeTarget", plugins: ["Plugin"]), - .plugin(name: "Plugin", capability: .buildTool), - ]) - """) + // swift-tools-version: \(toolsVersion.description) + import PackageDescription + let package = Package(name: "MyPackage", + targets: [ + .target(name: "SomeTarget", plugins: ["Plugin"]), + .plugin(name: "Plugin", capability: .buildTool), + ]) + """ + ) let targetSourceFile = packageDir.appending(components: "Sources", "SomeTarget", "dummy.swift") try localFileSystem.createDirectory(targetSourceFile.parentDirectory, recursive: true) @@ -462,29 +466,32 @@ struct PluginTests { let pluginSourceFile = packageDir.appending(components: "Plugins", "Plugin", "plugin.swift") try localFileSystem.createDirectory(pluginSourceFile.parentDirectory, recursive: true) - try localFileSystem.writeFileContents(pluginSourceFile, string: """ - import PackagePlugin - #if os(Android) - let touchExe = "/system/bin/touch" - #else - let touchExe = "/usr/bin/touch" - #endif - - @main - struct Plugin: BuildToolPlugin { - func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] { - return [ - .buildCommand( - displayName: "empty", - executable: .init(touchExe), - arguments: [context.pluginWorkDirectory.appending("best.txt")], - inputFiles: [], - outputFiles: [] - ) - ] - } - } - """) + try localFileSystem.writeFileContents( + pluginSourceFile, + string: """ + import PackagePlugin + #if os(Android) + let touchExe = "/system/bin/touch" + #else + let touchExe = "/usr/bin/touch" + #endif + + @main + struct Plugin: BuildToolPlugin { + func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] { + return [ + .buildCommand( + displayName: "empty", + executable: .init(touchExe), + arguments: [context.pluginWorkDirectory.appending("best.txt")], + inputFiles: [], + outputFiles: [] + ) + ] + } + } + """ + ) } try await withKnownIssue { @@ -496,7 +503,7 @@ struct PluginTests { try createPackageUnderTest(packageDir: packageDir, toolsVersion: .v5_9) let (_, stderr) = try await executeSwiftBuild( packageDir, - env: ["SWIFT_DRIVER_SWIFTSCAN_LIB" : "/this/is/a/bad/path"], + env: ["SWIFT_DRIVER_SWIFTSCAN_LIB": "/this/is/a/bad/path"], buildSystem: buildSystem, ) #expect(stderr.contains("warning: Build tool command 'empty' (applied to target 'SomeTarget') does not declare any output files"), "expected warning not emitted") @@ -508,14 +515,16 @@ struct PluginTests { try createPackageUnderTest(packageDir: packageDir, toolsVersion: .v6_0) let (stdout, stderr2) = try await executeSwiftBuild( packageDir, - env: ["SWIFT_DRIVER_SWIFTSCAN_LIB" : "/this/is/a/bad/path"], + env: ["SWIFT_DRIVER_SWIFTSCAN_LIB": "/this/is/a/bad/path"], buildSystem: buildSystem, ) #expect(stdout.contains("Build complete!")) #expect(!stderr2.contains("error:")) #expect(localFileSystem.exists(pathOfGeneratedFile), "plugin did not run, generated file does not exist at \(pathOfGeneratedFile.pathString)") } - } when: { ProcessInfo.hostOperatingSystem == .windows } + } when: { + ProcessInfo.hostOperatingSystem == .windows + } } @Test( @@ -533,142 +542,142 @@ struct PluginTests { try localFileSystem.writeFileContents( manifestFile, string: """ - // swift-tools-version: 5.6 - import PackageDescription - let package = Package( - name: "MyPackage", - dependencies: [ - .package(name: "HelperPackage", path: "VendoredDependencies/HelperPackage") - ], - targets: [ - .target( - name: "MyLibrary", - dependencies: [ - .product(name: "HelperLibrary", package: "HelperPackage") - ] - ), - .plugin( - name: "PluginPrintingInfo", - capability: .command( - intent: .custom(verb: "print-info", description: "Description of the command"), - permissions: [.writeToPackageDirectory(reason: "Reason for wanting to write to package directory")] - ) - ), - .plugin( - name: "PluginFailingWithError", - capability: .command( - intent: .custom(verb: "fail-with-error", description: "Sample plugin that throws an error") - ) - ), - .plugin( - name: "PluginFailingWithoutError", - capability: .command( - intent: .custom(verb: "fail-without-error", description: "Sample plugin that exits without error") - ) - ), - .plugin( - name: "NeverendingPlugin", - capability: .command( - intent: .custom(verb: "neverending-plugin", description: "A plugin that doesn't end running") - ) - ), - ] - ) - """ + // swift-tools-version: 5.6 + import PackageDescription + let package = Package( + name: "MyPackage", + dependencies: [ + .package(name: "HelperPackage", path: "VendoredDependencies/HelperPackage") + ], + targets: [ + .target( + name: "MyLibrary", + dependencies: [ + .product(name: "HelperLibrary", package: "HelperPackage") + ] + ), + .plugin( + name: "PluginPrintingInfo", + capability: .command( + intent: .custom(verb: "print-info", description: "Description of the command"), + permissions: [.writeToPackageDirectory(reason: "Reason for wanting to write to package directory")] + ) + ), + .plugin( + name: "PluginFailingWithError", + capability: .command( + intent: .custom(verb: "fail-with-error", description: "Sample plugin that throws an error") + ) + ), + .plugin( + name: "PluginFailingWithoutError", + capability: .command( + intent: .custom(verb: "fail-without-error", description: "Sample plugin that exits without error") + ) + ), + .plugin( + name: "NeverendingPlugin", + capability: .command( + intent: .custom(verb: "neverending-plugin", description: "A plugin that doesn't end running") + ) + ), + ] + ) + """ ) let librarySourceFile = packageDir.appending(components: "Sources", "MyLibrary", "library.swift") try localFileSystem.createDirectory(librarySourceFile.parentDirectory, recursive: true) try localFileSystem.writeFileContents( librarySourceFile, string: """ - public func Foo() { } - """ + public func Foo() { } + """ ) let printingPluginSourceFile = packageDir.appending(components: "Plugins", "PluginPrintingInfo", "plugin.swift") try localFileSystem.createDirectory(printingPluginSourceFile.parentDirectory, recursive: true) try localFileSystem.writeFileContents( printingPluginSourceFile, string: """ - import PackagePlugin - @main struct MyCommandPlugin: CommandPlugin { - func performCommand( - context: PluginContext, - arguments: [String] - ) throws { - // Check the identity of the root packages. - print("Root package is \\(context.package.displayName).") - - // Check that we can find a tool in the toolchain. - let swiftc = try context.tool(named: "swiftc") - print("Found the swiftc tool at \\(swiftc.path).") + import PackagePlugin + @main struct MyCommandPlugin: CommandPlugin { + func performCommand( + context: PluginContext, + arguments: [String] + ) throws { + // Check the identity of the root packages. + print("Root package is \\(context.package.displayName).") + + // Check that we can find a tool in the toolchain. + let swiftc = try context.tool(named: "swiftc") + print("Found the swiftc tool at \\(swiftc.path).") + } } - } - """ + """ ) let pluginFailingWithErrorSourceFile = packageDir.appending(components: "Plugins", "PluginFailingWithError", "plugin.swift") try localFileSystem.createDirectory(pluginFailingWithErrorSourceFile.parentDirectory, recursive: true) try localFileSystem.writeFileContents( pluginFailingWithErrorSourceFile, string: """ - import PackagePlugin - @main struct MyCommandPlugin: CommandPlugin { - func performCommand( - context: PluginContext, - arguments: [String] - ) throws { - // Print some output that should appear before the error diagnostic. - print("This text should appear before the uncaught thrown error.") - - // Throw an uncaught error that should be reported as a diagnostics. - throw "This is the uncaught thrown error." + import PackagePlugin + @main struct MyCommandPlugin: CommandPlugin { + func performCommand( + context: PluginContext, + arguments: [String] + ) throws { + // Print some output that should appear before the error diagnostic. + print("This text should appear before the uncaught thrown error.") + + // Throw an uncaught error that should be reported as a diagnostics. + throw "This is the uncaught thrown error." + } } - } - extension String: Error { } - """ + extension String: Error { } + """ ) let pluginFailingWithoutErrorSourceFile = packageDir.appending(components: "Plugins", "PluginFailingWithoutError", "plugin.swift") try localFileSystem.createDirectory(pluginFailingWithoutErrorSourceFile.parentDirectory, recursive: true) try localFileSystem.writeFileContents( pluginFailingWithoutErrorSourceFile, string: """ - import PackagePlugin - import Foundation - @main struct MyCommandPlugin: CommandPlugin { - func performCommand( - context: PluginContext, - arguments: [String] - ) throws { - // Print some output that should appear before we exit. - print("This text should appear before we exit.") - - // Just exit with an error code without an emitting error. - exit(1) + import PackagePlugin + import Foundation + @main struct MyCommandPlugin: CommandPlugin { + func performCommand( + context: PluginContext, + arguments: [String] + ) throws { + // Print some output that should appear before we exit. + print("This text should appear before we exit.") + + // Just exit with an error code without an emitting error. + exit(1) + } } - } - extension String: Error { } - """ + extension String: Error { } + """ ) let neverendingPluginSourceFile = packageDir.appending(components: "Plugins", "NeverendingPlugin", "plugin.swift") try localFileSystem.createDirectory(neverendingPluginSourceFile.parentDirectory, recursive: true) try localFileSystem.writeFileContents( neverendingPluginSourceFile, string: """ - import PackagePlugin - import Foundation - @main struct MyCommandPlugin: CommandPlugin { - func performCommand( - context: PluginContext, - arguments: [String] - ) throws { - // Print some output that should appear before we exit. - print("This text should appear before we exit.") - - // Just exit with an error code without an emitting error. - exit(1) + import PackagePlugin + import Foundation + @main struct MyCommandPlugin: CommandPlugin { + func performCommand( + context: PluginContext, + arguments: [String] + ) throws { + // Print some output that should appear before we exit. + print("This text should appear before we exit.") + + // Just exit with an error code without an emitting error. + exit(1) + } } - } - extension String: Error { } - """ + extension String: Error { } + """ ) // Create the sample vendored dependency package. @@ -677,23 +686,23 @@ struct PluginTests { try localFileSystem.writeFileContents( library1Path, string: """ - // swift-tools-version: 5.5 - import PackageDescription - let package = Package( - name: "HelperPackage", - products: [ - .library( - name: "HelperLibrary", - targets: ["HelperLibrary"] - ), - ], - targets: [ - .target( - name: "HelperLibrary" - ), - ] - ) - """ + // swift-tools-version: 5.5 + import PackageDescription + let package = Package( + name: "HelperPackage", + products: [ + .library( + name: "HelperLibrary", + targets: ["HelperLibrary"] + ), + ], + targets: [ + .target( + name: "HelperLibrary" + ), + ] + ) + """ ) let library2Path = packageDir.appending(components: "VendoredDependencies", "HelperPackage", "Sources", "HelperLibrary", "library.swift") @@ -701,8 +710,8 @@ struct PluginTests { try localFileSystem.writeFileContents( library2Path, string: """ - public func Bar() { } - """ + public func Bar() { } + """ ) // Load a workspace from the package. @@ -733,7 +742,7 @@ struct PluginTests { let package = try #require(packageGraph.rootPackages.first) // Find the regular target in our test package. - let libraryTarget = try #require(package.modules.map(\.underlying).first{ $0.name == "MyLibrary" } as? SwiftModule) + let libraryTarget = try #require(package.modules.map(\.underlying).first { $0.name == "MyLibrary" } as? SwiftModule) #expect(libraryTarget.type == .library) // Set up a delegate to handle callbacks from the command plugin. @@ -759,10 +768,12 @@ struct PluginTests { // Add each line of emitted output as a `.info` diagnostic. dispatchPrecondition(condition: .onQueue(delegateQueue)) let textlines = String(decoding: data, as: UTF8.self).split(whereSeparator: { $0.isNewline }) - print(textlines.map{ "[TEXT] \($0)" }.joined(separator: "\n")) - diagnostics.append(contentsOf: textlines.map{ - Basics.Diagnostic(severity: .info, message: String($0), metadata: .none) - }) + print(textlines.map { "[TEXT] \($0)" }.joined(separator: "\n")) + diagnostics.append( + contentsOf: textlines.map { + Basics.Diagnostic(severity: .info, message: String($0), metadata: .none) + } + ) } func pluginEmittedDiagnostic(_ diagnostic: Basics.Diagnostic) { @@ -787,7 +798,7 @@ struct PluginTests { diagnosticsChecker: (DiagnosticsTestResult) throws -> Void ) async throws { // Find the named plugin. - let plugins = package.modules.compactMap{ $0.underlying as? PluginModule } + let plugins = package.modules.compactMap { $0.underlying as? PluginModule } let plugin = try #require(plugins.first(where: { $0.name == pluginName }), "There is no plugin target named ‘\(pluginName)’") try #require(plugin.type == .plugin, "Target \(plugin) isn’t a plugin") @@ -810,42 +821,40 @@ struct PluginTests { let toolSearchDirectories = [try UserToolchain.default.swiftCompilerPath.parentDirectory] let success = try await withCheckedThrowingContinuation { continuation in - plugin.invoke( - action: .performCommand(package: package, arguments: arguments), - buildEnvironment: BuildEnvironment(platform: .macOS, configuration: .debug), - scriptRunner: scriptRunner, - workingDirectory: package.path, - outputDirectory: pluginDir.appending("output"), - toolSearchDirectories: toolSearchDirectories, - accessibleTools: [:], - writableDirectories: [pluginDir.appending("output")], - readOnlyDirectories: [package.path], - allowNetworkConnections: [], - pkgConfigDirectories: [], - sdkRootPath: nil, - fileSystem: localFileSystem, - modulesGraph: packageGraph, - observabilityScope: observability.topScope, - callbackQueue: delegateQueue, - delegate: delegate, - completion: { - continuation.resume(with: $0) - } - ) + plugin.invoke( + action: .performCommand(package: package, arguments: arguments), + buildEnvironment: BuildEnvironment(platform: .macOS, configuration: .debug), + scriptRunner: scriptRunner, + workingDirectory: package.path, + outputDirectory: pluginDir.appending("output"), + toolSearchDirectories: toolSearchDirectories, + accessibleTools: [:], + writableDirectories: [pluginDir.appending("output")], + readOnlyDirectories: [package.path], + allowNetworkConnections: [], + pkgConfigDirectories: [], + sdkRootPath: nil, + fileSystem: localFileSystem, + modulesGraph: packageGraph, + observabilityScope: observability.topScope, + callbackQueue: delegateQueue, + delegate: delegate, + completion: { + continuation.resume(with: $0) + } + ) } if expectFailure { #expect(!success, "expected command to fail, but it succeeded") - } - else { + } else { #expect(success, "expected command to succeed, but it failed", sourceLocation: sourceLocation) } - } - catch { + } catch { Issue.record("error \(String(describing: error))", sourceLocation: sourceLocation) } // Check that we didn't end up with any completely empty diagnostics. - #expect(observability.diagnostics.first{ $0.message.isEmpty } == nil) + #expect(observability.diagnostics.first { $0.message.isEmpty } == nil) // Invoke the diagnostics checker for the plugin output. try expectDiagnostics(delegate.diagnostics, problemsOnly: false, sourceLocation: sourceLocation, handler: diagnosticsChecker) @@ -877,7 +886,7 @@ struct PluginTests { arguments: SupportedBuildSystemOnAllPlatforms, ) func testLocalAndRemoteToolDependencies(buildSystem: BuildSystemProvider.Kind) async throws { - try await withKnownIssue (isIntermittent: true) { + try await withKnownIssue(isIntermittent: true) { try await fixture(name: "Miscellaneous/Plugins/PluginUsingLocalAndRemoteTool") { path in let (stdout, stderr) = try await executeSwiftPackage( path.appending("MyLibrary"), @@ -901,7 +910,7 @@ struct PluginTests { #expect(stdout.contains("A message from the implied local tool."), "stdout:\n\(stderr)\n\(stdout)") } } when: { - ProcessInfo.hostOperatingSystem == .windows // Intermittent depending on the file path length + ProcessInfo.hostOperatingSystem == .windows // Intermittent depending on the file path length } } @@ -937,7 +946,7 @@ struct PluginTests { // Make sure that the use of plugins doesn't bleed into the use of plugins by tools. let testTargetMappings = try packageGraph.computeTestModulesForExecutableModules() for (target, testTargets) in testTargetMappings { - #expect(!testTargets.contains{ $0.name == "MySourceGenPluginTests" }, "target: \(target), testTargets: \(testTargets)") + #expect(!testTargets.contains { $0.name == "MySourceGenPluginTests" }, "target: \(target), testTargets: \(testTargets)") } } } @@ -955,58 +964,58 @@ struct PluginTests { try localFileSystem.writeFileContents( packageDir.appending(components: "Package.swift"), string: """ - // swift-tools-version: 5.6 - import PackageDescription - let package = Package( - name: "MyPackage", - products: [ - .library( - name: "MyLibrary", - targets: ["MyLibrary"] - ), - ], - targets: [ - .target( - name: "MyLibrary" - ), - .plugin( - name: "NeverendingPlugin", - capability: .command( - intent: .custom(verb: "neverending-plugin", description: "Help description") - ) - ), - ] - ) - """ + // swift-tools-version: 5.6 + import PackageDescription + let package = Package( + name: "MyPackage", + products: [ + .library( + name: "MyLibrary", + targets: ["MyLibrary"] + ), + ], + targets: [ + .target( + name: "MyLibrary" + ), + .plugin( + name: "NeverendingPlugin", + capability: .command( + intent: .custom(verb: "neverending-plugin", description: "Help description") + ) + ), + ] + ) + """ ) let myLibraryTargetDir = packageDir.appending(components: "Sources", "MyLibrary") try localFileSystem.createDirectory(myLibraryTargetDir, recursive: true) try localFileSystem.writeFileContents( myLibraryTargetDir.appending("library.swift"), string: """ - public func GetGreeting() -> String { return "Hello" } - """ + public func GetGreeting() -> String { return "Hello" } + """ ) let neverendingPluginTargetDir = packageDir.appending(components: "Plugins", "NeverendingPlugin") try localFileSystem.createDirectory(neverendingPluginTargetDir, recursive: true) try localFileSystem.writeFileContents( neverendingPluginTargetDir.appending("plugin.swift"), string: """ - import PackagePlugin - import Foundation - @main struct NeverendingPlugin: CommandPlugin { - func performCommand( - context: PluginContext, - arguments: [String] - ) throws { - print("pid: \\(ProcessInfo.processInfo.processIdentifier)") - while true { - Thread.sleep(forTimeInterval: 1.0) - print("still here") + import PackagePlugin + import Foundation + @main struct NeverendingPlugin: CommandPlugin { + func performCommand( + context: PluginContext, + arguments: [String] + ) throws { + print("pid: \\(ProcessInfo.processInfo.processIdentifier)") + while true { + Thread.sleep(forTimeInterval: 1.0) + print("still here") + } } } - } - """ + """ ) // Load a workspace from the package. @@ -1040,7 +1049,7 @@ struct PluginTests { let libraryTarget = try #require( package.modules .map(\.underlying) - .first{ $0.name == "MyLibrary" } as? SwiftModule + .first { $0.name == "MyLibrary" } as? SwiftModule ) #expect(libraryTarget.type == .library) @@ -1068,9 +1077,11 @@ struct PluginTests { // Add each line of emitted output as a `.info` diagnostic. dispatchPrecondition(condition: .onQueue(delegateQueue)) let textlines = String(decoding: data, as: UTF8.self).split(whereSeparator: { $0.isNewline }) - diagnostics.append(contentsOf: textlines.map{ - Basics.Diagnostic(severity: .info, message: String($0), metadata: .none) - }) + diagnostics.append( + contentsOf: textlines.map { + Basics.Diagnostic(severity: .info, message: String($0), metadata: .none) + } + ) // If we don't already have the process identifier, we try to find it. if parsedProcessIdentifier == .none { @@ -1080,7 +1091,7 @@ struct PluginTests { assert(match.numberOfRanges == 2) return Int((string as NSString).substring(with: match.range(at: 1))) } - parsedProcessIdentifier = textlines.compactMap{ parseProcessIdentifier(String($0)) }.first + parsedProcessIdentifier = textlines.compactMap { parseProcessIdentifier(String($0)) }.first } } @@ -1153,9 +1164,9 @@ struct PluginTests { // Check that it's running (we do this by asking for its priority — this only works on some platforms). #if os(macOS) - errno = 0 - getpriority(Int32(PRIO_PROCESS), UInt32(pid)) - #expect(errno == 0, "unexpectedly got errno \(errno) when trying to check process \(pid)") + errno = 0 + getpriority(Int32(PRIO_PROCESS), UInt32(pid)) + #expect(errno == 0, "unexpectedly got errno \(errno) when trying to check process \(pid)") #endif // Cancel the plugin task @@ -1166,9 +1177,9 @@ struct PluginTests { // Check that it's no longer running (we do this by asking for its priority — this only works on some platforms). #if os(macOS) - errno = 0 - getpriority(Int32(PRIO_PROCESS), UInt32(pid)) - #expect(errno == ESRCH, "unexpectedly got errno \(errno) when trying to check process \(pid)") + errno = 0 + getpriority(Int32(PRIO_PROCESS), UInt32(pid)) + #expect(errno == ESRCH, "unexpectedly got errno \(errno) when trying to check process \(pid)") #endif // Ensure the task was actually cancelled @@ -1181,7 +1192,6 @@ struct PluginTests { // Also acceptable - plugin may have been terminated } - } } @@ -1195,32 +1205,32 @@ struct PluginTests { try localFileSystem.writeFileContents( packageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.6 - import PackageDescription - let package = Package( - name: "MyPackage", - dependencies: [ - .package(name: "BuildToolPluginPackage", path: "VendoredDependencies/BuildToolPluginPackage"), - .package(name: "UnusedBuildToolPluginPackage", path: "VendoredDependencies/UnusedBuildToolPluginPackage"), - .package(name: "CommandPluginPackage", path: "VendoredDependencies/CommandPluginPackage") - ], - targets: [ - .target( - name: "MyLibrary", - path: ".", - plugins: [ - .plugin(name: "BuildToolPlugin", package: "BuildToolPluginPackage") - ] - ), - ] - ) - """ + // swift-tools-version: 5.6 + import PackageDescription + let package = Package( + name: "MyPackage", + dependencies: [ + .package(name: "BuildToolPluginPackage", path: "VendoredDependencies/BuildToolPluginPackage"), + .package(name: "UnusedBuildToolPluginPackage", path: "VendoredDependencies/UnusedBuildToolPluginPackage"), + .package(name: "CommandPluginPackage", path: "VendoredDependencies/CommandPluginPackage") + ], + targets: [ + .target( + name: "MyLibrary", + path: ".", + plugins: [ + .plugin(name: "BuildToolPlugin", package: "BuildToolPluginPackage") + ] + ), + ] + ) + """ ) try localFileSystem.writeFileContents( packageDir.appending("Library.swift"), string: """ - public var Foo: String - """ + public var Foo: String + """ ) // Create the depended-upon package that vends a build tool plugin that is used by the main package. @@ -1229,34 +1239,34 @@ struct PluginTests { try localFileSystem.writeFileContents( buildToolPluginPackageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.6 - import PackageDescription - let package = Package( - name: "BuildToolPluginPackage", - products: [ - .plugin( - name: "BuildToolPlugin", - targets: ["BuildToolPlugin"]) - ], - targets: [ - .plugin( - name: "BuildToolPlugin", - capability: .buildTool(), - path: ".") - ] - ) - """ + // swift-tools-version: 5.6 + import PackageDescription + let package = Package( + name: "BuildToolPluginPackage", + products: [ + .plugin( + name: "BuildToolPlugin", + targets: ["BuildToolPlugin"]) + ], + targets: [ + .plugin( + name: "BuildToolPlugin", + capability: .buildTool(), + path: ".") + ] + ) + """ ) try localFileSystem.writeFileContents( buildToolPluginPackageDir.appending("Plugin.swift"), string: """ - import PackagePlugin - @main struct MyPlugin: BuildToolPlugin { - func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { - return [] + import PackagePlugin + @main struct MyPlugin: BuildToolPlugin { + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + return [] + } } - } - """ + """ ) // Create the depended-upon package that vends a build tool plugin that is not used by the main package. @@ -1265,34 +1275,34 @@ struct PluginTests { try localFileSystem.writeFileContents( unusedBuildToolPluginPackageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.6 - import PackageDescription - let package = Package( - name: "UnusedBuildToolPluginPackage", - products: [ - .plugin( - name: "UnusedBuildToolPlugin", - targets: ["UnusedBuildToolPlugin"]) - ], - targets: [ - .plugin( - name: "UnusedBuildToolPlugin", - capability: .buildTool(), - path: ".") - ] - ) - """ + // swift-tools-version: 5.6 + import PackageDescription + let package = Package( + name: "UnusedBuildToolPluginPackage", + products: [ + .plugin( + name: "UnusedBuildToolPlugin", + targets: ["UnusedBuildToolPlugin"]) + ], + targets: [ + .plugin( + name: "UnusedBuildToolPlugin", + capability: .buildTool(), + path: ".") + ] + ) + """ ) try localFileSystem.writeFileContents( unusedBuildToolPluginPackageDir.appending("Plugin.swift"), string: """ - import PackagePlugin - @main struct MyPlugin: BuildToolPlugin { - func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { - return [] + import PackagePlugin + @main struct MyPlugin: BuildToolPlugin { + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + return [] + } } - } - """ + """ ) // Create the depended-upon package that vends a command plugin. @@ -1301,33 +1311,33 @@ struct PluginTests { try localFileSystem.writeFileContents( commandPluginPackageDir.appending("Package.swift"), string: """ - // swift-tools-version: 5.6 - import PackageDescription - let package = Package( - name: "CommandPluginPackage", - products: [ - .plugin( - name: "CommandPlugin", - targets: ["CommandPlugin"]) - ], - targets: [ - .plugin( - name: "CommandPlugin", - capability: .command(intent: .custom(verb: "how", description: "why")), - path: ".") - ] - ) - """ + // swift-tools-version: 5.6 + import PackageDescription + let package = Package( + name: "CommandPluginPackage", + products: [ + .plugin( + name: "CommandPlugin", + targets: ["CommandPlugin"]) + ], + targets: [ + .plugin( + name: "CommandPlugin", + capability: .command(intent: .custom(verb: "how", description: "why")), + path: ".") + ] + ) + """ ) try localFileSystem.writeFileContents( commandPluginPackageDir.appending("Plugin.swift"), string: """ - import PackagePlugin - @main struct MyPlugin: CommandPlugin { - func performCommand(context: PluginContext, targets: [Target], arguments: [String]) throws { + import PackagePlugin + @main struct MyPlugin: CommandPlugin { + func performCommand(context: PluginContext, targets: [Target], arguments: [String]) throws { + } } - } - """ + """ ) // Load a workspace from the package. @@ -1428,24 +1438,25 @@ struct PluginTests { .issue("https://github.com/swiftlang/swift-package-manager/issues/9040", relationship: .verifies), .IssueWindowsCannotSaveAttachment, .requiresSwiftConcurrencySupport, - arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), try getFiles(in: RelativePath(validating: "Fixtures/Miscellaneous/Plugins/PluginsAndSnippets/Snippets"), matchingExtension: "swift",), + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + try getFiles(in: RelativePath(validating: "Fixtures/Miscellaneous/Plugins/PluginsAndSnippets/Snippets"), matchingExtension: "swift", ), ) func testBasicBuildIndividualSnippets( data: BuildData, targetPath: RelativePath, ) async throws { try await withKnownIssue(isIntermittent: true) { - try await fixture(name: "Miscellaneous/Plugins/PluginsAndSnippets") { fixturePath in - let targetName = targetPath.basenameWithoutExt - await #expect(throws: Never.self) { - let _ = try await executeSwiftBuild( - fixturePath, - configuration: data.config, - extraArgs: ["--product", targetName], - buildSystem: data.buildSystem, - ) + try await fixture(name: "Miscellaneous/Plugins/PluginsAndSnippets") { fixturePath in + let targetName = targetPath.basenameWithoutExt + await #expect(throws: Never.self) { + let _ = try await executeSwiftBuild( + fixturePath, + configuration: data.config, + extraArgs: ["--product", targetName], + buildSystem: data.buildSystem, + ) + } } - } } when: { ProcessInfo.hostOperatingSystem == .windows && data.buildSystem == .swiftbuild } @@ -1455,7 +1466,8 @@ struct PluginTests { .issue("https://github.com/swiftlang/swift-package-manager/issues/9040", relationship: .verifies), .IssueWindowsCannotSaveAttachment, .requiresSwiftConcurrencySupport, - arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), try getFiles(in: RelativePath(validating: "Fixtures/Miscellaneous/Plugins/PluginsAndSnippets/Snippets"), matchingExtension: "swift",), + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + try getFiles(in: RelativePath(validating: "Fixtures/Miscellaneous/Plugins/PluginsAndSnippets/Snippets"), matchingExtension: "swift", ), ) func testBasicRunSnippets( data: BuildData, @@ -1463,16 +1475,16 @@ struct PluginTests { ) async throws { let targetName = targetPath.basenameWithoutExt try await withKnownIssue(isIntermittent: true) { - try await fixture(name: "Miscellaneous/Plugins/PluginsAndSnippets") { fixturePath in - let (stdout, stderr) = try await executeSwiftRun( - fixturePath, - targetName, - configuration: data.config, - buildSystem: data.buildSystem, - ) + try await fixture(name: "Miscellaneous/Plugins/PluginsAndSnippets") { fixturePath in + let (stdout, stderr) = try await executeSwiftRun( + fixturePath, + targetName, + configuration: data.config, + buildSystem: data.buildSystem, + ) - #expect(stdout.contains("hello, snippets"), "stderr: \(stderr)") - } + #expect(stdout.contains("hello, snippets"), "stderr: \(stderr)") + } } when: { [.windows].contains(ProcessInfo.hostOperatingSystem) && data.buildSystem == .swiftbuild } @@ -1491,7 +1503,7 @@ struct PluginTests { func testIncorrectDependencies( buildSystem: BuildSystemProvider.Kind, ) async throws { - try await withKnownIssue (isIntermittent: true) { + try await withKnownIssue(isIntermittent: true) { try await fixture(name: "Miscellaneous/Plugins") { path in let (stdout, stderr) = try await executeSwiftBuild( path.appending("IncorrectDependencies"), @@ -1503,7 +1515,7 @@ struct PluginTests { } } when: { (ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild) - || (ProcessInfo.hostOperatingSystem == .linux && buildSystem == .swiftbuild && CiEnvironment.runningInSmokeTestPipeline) + || (ProcessInfo.hostOperatingSystem == .linux && buildSystem == .swiftbuild && CiEnvironment.runningInSmokeTestPipeline) } } @@ -1579,7 +1591,7 @@ struct PluginTests { let (stdout, stderr) = try await executeSwiftBuild( fixturePath.appending("SwiftFilePlugin"), configuration: .debug, - extraArgs: [ "--verbose"], + extraArgs: ["--verbose"], buildSystem: buildSystem, ) switch buildSystem { @@ -1698,10 +1710,11 @@ struct PluginTests { ) async throws { try await withKnownIssue { try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let buildArgs: [String] = switch buildSystem { + let buildArgs: [String] = + switch buildSystem { case .native, .xcode: [] case .swiftbuild: ["-v"] - } + } let (stdout, stderr) = try await executeSwiftBuild( fixturePath.appending(component: "MySourceGenPlugin"), configuration: .debug, diff --git a/Tests/FunctionalTests/ResourcesTests.swift b/Tests/FunctionalTests/ResourcesTests.swift index 0d5eeae6a22..f7b0c0839fa 100644 --- a/Tests/FunctionalTests/ResourcesTests.swift +++ b/Tests/FunctionalTests/ResourcesTests.swift @@ -19,8 +19,8 @@ final class ResourcesTests: XCTestCase { func testSimpleResources() async throws { try XCTSkipOnWindows( because: """ - Invalid path. Possibly related to https://github.com/swiftlang/swift-package-manager/issues/8511 or https://github.com/swiftlang/swift-package-manager/issues/8602 - """, + Invalid path. Possibly related to https://github.com/swiftlang/swift-package-manager/issues/8511 or https://github.com/swiftlang/swift-package-manager/issues/8602 + """, skipPlatformCi: true, ) @@ -29,8 +29,8 @@ final class ResourcesTests: XCTestCase { // Objective-C module requires macOS #if os(macOS) - executables.append("SeaResource") - executables.append("CPPResource") + executables.append("SeaResource") + executables.append("CPPResource") #endif for execName in executables { @@ -54,19 +54,22 @@ final class ResourcesTests: XCTestCase { let exec = AbsolutePath(".build/debug/exe", relativeTo: fixturePath) // Note: Source from LANG and -AppleLanguages on command line for Linux resources let output = try await AsyncProcess.checkNonZeroExit(args: exec.pathString, "-AppleLanguages", "(en_US)").withSwiftLineEnding - XCTAssertEqual(output, """ + XCTAssertEqual( + output, + """ ¡Hola Mundo! Hallo Welt! Bonjour le monde ! - """) + """ + ) } } func testResourcesInMixedClangPackage() async throws { #if !os(macOS) - // Running swift-test fixtures on linux is not yet possible. - try XCTSkipIf(true, "test is only supported on macOS") + // Running swift-test fixtures on linux is not yet possible. + try XCTSkipIf(true, "test is only supported on macOS") #endif try await fixtureXCTest(name: "Resources/Simple") { fixturePath in @@ -84,16 +87,17 @@ final class ResourcesTests: XCTestCase { // Objective-C module requires macOS #if os(macOS) - executables.append("SeaResource") + executables.append("SeaResource") #endif - let binPath = try AbsolutePath(validating: - await executeSwiftBuild( - fixturePath, - configuration: .release, - extraArgs: ["--show-bin-path"], - buildSystem: .native, - ).stdout + let binPath = try AbsolutePath( + validating: + await executeSwiftBuild( + fixturePath, + configuration: .release, + extraArgs: ["--show-bin-path"], + buildSystem: .native, + ).stdout .trimmingCharacters(in: .whitespacesAndNewlines) ) @@ -141,8 +145,8 @@ final class ResourcesTests: XCTestCase { func testResourceBundleInClangPackageWhenRunningSwiftTest() async throws { #if !os(macOS) - // Running swift-test fixtures on linux is not yet possible. - try XCTSkipIf(true, "test is only supported on macOS") + // Running swift-test fixtures on linux is not yet possible. + try XCTSkipIf(true, "test is only supported on macOS") #endif try await fixtureXCTest(name: "Resources/Simple") { fixturePath in @@ -164,7 +168,10 @@ final class ResourcesTests: XCTestCase { let result = try await AsyncProcess.checkNonZeroExit(args: execPath.pathString) XCTAssertMatch(result, .contains("hello world")) let resourcePath = fixturePath.appending( - components: "Sources", "EmbedInCodeSimple", "best.txt") + components: "Sources", + "EmbedInCodeSimple", + "best.txt" + ) // Check incremental builds for i in 0..<2 { @@ -175,7 +182,7 @@ final class ResourcesTests: XCTestCase { fixturePath, buildSystem: .native, ) - // Run the executable again. + // Run the executable again. let result2 = try await AsyncProcess.checkNonZeroExit(args: execPath.pathString) XCTAssertMatch(result2, .contains("\(content)")) } @@ -191,23 +198,27 @@ final class ResourcesTests: XCTestCase { try localFileSystem.writeFileContents( manifestFile, string: """ - // swift-tools-version: 6.0 - import PackageDescription - let package = Package(name: "MyPackage", - targets: [ - .executableTarget( - name: "exec", - resources: [.copy("../resources")] - ) - ]) - """) + // swift-tools-version: 6.0 + import PackageDescription + let package = Package(name: "MyPackage", + targets: [ + .executableTarget( + name: "exec", + resources: [.copy("../resources")] + ) + ]) + """ + ) let targetSourceFile = packageDir.appending(components: "Sources", "exec", "main.swift") try localFileSystem.createDirectory(targetSourceFile.parentDirectory, recursive: true) - try localFileSystem.writeFileContents(targetSourceFile, string: """ - import Foundation - print(Bundle.module.resourcePath ?? "") - """) + try localFileSystem.writeFileContents( + targetSourceFile, + string: """ + import Foundation + print(Bundle.module.resourcePath ?? "") + """ + ) let resource = packageDir.appending(components: "Sources", "resources", "best.txt") try localFileSystem.createDirectory(resource.parentDirectory, recursive: true) @@ -215,12 +226,12 @@ final class ResourcesTests: XCTestCase { let (_, stderr) = try await executeSwiftBuild( packageDir, - env: ["SWIFT_DRIVER_SWIFTSCAN_LIB" : "/this/is/a/bad/path"], + env: ["SWIFT_DRIVER_SWIFTSCAN_LIB": "/this/is/a/bad/path"], buildSystem: .native, ) // Filter some unrelated output that could show up on stderr. let filteredStderr = stderr.components(separatedBy: "\n").filter { !$0.contains("[logging]") } - .filter { !$0.contains("Unable to locate libSwiftScan") }.joined(separator: "\n") + .filter { !$0.contains("Unable to locate libSwiftScan") }.joined(separator: "\n") XCTAssertEqual(filteredStderr, "", "unexpectedly received error output: \(stderr)") let builtProductsDir = packageDir.appending(components: [".build", "debug"]) diff --git a/Tests/FunctionalTests/StaticBinaryLibrary.swift b/Tests/FunctionalTests/StaticBinaryLibrary.swift index 4806fd08113..294965f6a9f 100644 --- a/Tests/FunctionalTests/StaticBinaryLibrary.swift +++ b/Tests/FunctionalTests/StaticBinaryLibrary.swift @@ -41,11 +41,13 @@ struct StaticBinaryLibraryTests { extraArgs: ["--experimental-prune-unused-dependencies"], buildSystem: buildData.buildSystem, ) - #expect(stdout == """ - 42 - 42 + #expect( + stdout == """ + 42 + 42 - """) + """ + ) } } when: { ProcessInfo.hostOperatingSystem == .windows diff --git a/Tests/FunctionalTests/TaskBacktracesTests.swift b/Tests/FunctionalTests/TaskBacktracesTests.swift index c75a0c88dd6..cabe0c03148 100644 --- a/Tests/FunctionalTests/TaskBacktracesTests.swift +++ b/Tests/FunctionalTests/TaskBacktracesTests.swift @@ -44,9 +44,11 @@ struct TaskBacktraceTests { ) // Add a basic check that we produce backtrace output. The specifc formatting is tested by Swift Build. #expect(incrementalStderr.contains("Task backtrace:")) - #expect(incrementalStderr.split(separator: "\n").contains(where: { - $0.contains("Foo.swift' changed") - })) + #expect( + incrementalStderr.split(separator: "\n").contains(where: { + $0.contains("Foo.swift' changed") + }) + ) #expect(incrementalStdout.contains("Build complete!")) } } diff --git a/Tests/FunctionalTests/TestDiscoveryTests.swift b/Tests/FunctionalTests/TestDiscoveryTests.swift index 8a7064d1508..e9796900e5c 100644 --- a/Tests/FunctionalTests/TestDiscoveryTests.swift +++ b/Tests/FunctionalTests/TestDiscoveryTests.swift @@ -136,7 +136,7 @@ struct TestDiscoveryTests { arguments: SupportedBuildSystemOnAllPlatforms, ) func discovery_whenNoTests(_ buildSystem: BuildSystemProvider.Kind) async throws { - try await withKnownIssue(isIntermittent: true) { + try await withKnownIssue(isIntermittent: true) { try await fixture(name: "Miscellaneous/TestDiscovery/NoTests") { fixturePath in let (stdout, stderr) = try await executeSwiftTest(fixturePath, buildSystem: buildSystem) // in "swift test" build output goes to stderr @@ -150,9 +150,9 @@ struct TestDiscoveryTests { // in "swift test" test output goes to stdout #expect(stdout.contains("Executed 0 tests")) } - } when: { - buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows - } + } when: { + buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows + } } // FIXME: --build-system swiftbuild should support hand-authored entry points. @@ -166,7 +166,8 @@ struct TestDiscoveryTests { .tags( .Feature.CommandLineArguments.BuildSystem, ), - arguments: SupportedBuildSystemOnAllPlatforms, SwiftModule.testEntryPointNames + arguments: SupportedBuildSystemOnAllPlatforms, + SwiftModule.testEntryPointNames ) func entryPointOverride( _ buildSystem: BuildSystemProvider.Kind, @@ -233,9 +234,9 @@ struct TestDiscoveryTests { // in "swift test" test output goes to stdout let delimiter: String #if os(macOS) - delimiter = " " + delimiter = " " #else - delimiter = "." + delimiter = "." #endif #expect(stdout.contains("SimpleTests1\(delimiter)testExample1")) #expect(stdout.contains("SimpleTests1\(delimiter)testExample1_a")) @@ -291,9 +292,9 @@ struct TestDiscoveryTests { // in "swift test" test output goes to stdout let delimiter: String #if os(macOS) - delimiter = " " + delimiter = " " #else - delimiter = "." + delimiter = "." #endif #expect(stdout.contains("Tests3\(delimiter)test11")) #expect(stdout.contains("->Module1::Tests1::test11")) diff --git a/Tests/FunctionalTests/ToolsVersionTests.swift b/Tests/FunctionalTests/ToolsVersionTests.swift index c6da1339922..13952644fd9 100644 --- a/Tests/FunctionalTests/ToolsVersionTests.swift +++ b/Tests/FunctionalTests/ToolsVersionTests.swift @@ -41,7 +41,7 @@ struct ToolsVersionTests { let buildSystem = buildData.buildSystem let configuration = buildData.config try await withKnownIssue("https://github.com/swiftlang/swift-build/issues/609", isIntermittent: true) { - try await testWithTemporaryDirectory{ path in + try await testWithTemporaryDirectory { path in let fs = localFileSystem // Create a repo for the dependency to test against. @@ -131,7 +131,6 @@ struct ToolsVersionTests { let executableActualOutput = try await AsyncProcess.checkNonZeroExit(args: exe).spm_chomp() #expect(executableActualOutput == "foo@1.0") - // Set the tools version to something high. _ = try await executeSwiftPackage( primaryPath, diff --git a/Tests/FunctionalTests/TraitTests.swift b/Tests/FunctionalTests/TraitTests.swift index b5db4e797f0..94fb5ab3942 100644 --- a/Tests/FunctionalTests/TraitTests.swift +++ b/Tests/FunctionalTests/TraitTests.swift @@ -34,37 +34,40 @@ struct TraitTests { .tags( Tag.Feature.Command.Run, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func traits_whenNoFlagPassed( buildSystem: BuildSystemProvider.Kind, configuration: BuildConfiguration, ) async throws { try await withKnownIssue(isIntermittent: (ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild)) { - try await fixture(name: "Traits") { fixturePath in - let (stdout, stderr) = try await executeSwiftRun( - fixturePath.appending("Example"), - "Example", - configuration: configuration, - buildSystem: buildSystem, - ) - // We expect no warnings to be produced. Specifically no unused dependency warnings. - let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") - #expect(!stderr.contains(unusedDependencyRegex)) - #expect(stdout == """ - Package1Library1 trait1 enabled - Package2Library1 trait2 enabled - Package3Library1 trait3 enabled - Package4Library1 trait1 disabled - DEFINE1 enabled - DEFINE2 disabled - DEFINE3 disabled - - """) - } + try await fixture(name: "Traits") { fixturePath in + let (stdout, stderr) = try await executeSwiftRun( + fixturePath.appending("Example"), + "Example", + configuration: configuration, + buildSystem: buildSystem, + ) + // We expect no warnings to be produced. Specifically no unused dependency warnings. + let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") + #expect(!stderr.contains(unusedDependencyRegex)) + #expect( + stdout == """ + Package1Library1 trait1 enabled + Package2Library1 trait2 enabled + Package3Library1 trait3 enabled + Package4Library1 trait1 disabled + DEFINE1 enabled + DEFINE2 disabled + DEFINE3 disabled + + """ + ) + } } when: { (ProcessInfo.hostOperatingSystem == .windows && (CiEnvironment.runningInSmokeTestPipeline || buildSystem == .swiftbuild)) - || (buildSystem == .swiftbuild && [.windows].contains(ProcessInfo.hostOperatingSystem)) + || (buildSystem == .swiftbuild && [.windows].contains(ProcessInfo.hostOperatingSystem)) } } @@ -75,7 +78,8 @@ struct TraitTests { .tags( Tag.Feature.Command.Run, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func traits_whenTraitUnification( buildSystem: BuildSystemProvider.Kind, @@ -87,33 +91,35 @@ struct TraitTests { """, isIntermittent: (ProcessInfo.hostOperatingSystem == .windows), ) { - try await fixture(name: "Traits") { fixturePath in - let (stdout, stderr) = try await executeSwiftRun( - fixturePath.appending("Example"), - "Example", - configuration: configuration, - extraArgs: ["--traits", "default,Package9,Package10"], - buildSystem: buildSystem, - ) - // We expect no warnings to be produced. Specifically no unused dependency warnings. - let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") - #expect(!stderr.contains(unusedDependencyRegex)) - #expect(stdout == """ - Package1Library1 trait1 enabled - Package2Library1 trait2 enabled - Package3Library1 trait3 enabled - Package4Library1 trait1 disabled - Package10Library1 trait1 enabled - Package10Library1 trait2 enabled - Package10Library1 trait1 enabled - Package10Library1 trait2 enabled - Package10Library2 has been included. - DEFINE1 enabled - DEFINE2 disabled - DEFINE3 disabled - - """) - } + try await fixture(name: "Traits") { fixturePath in + let (stdout, stderr) = try await executeSwiftRun( + fixturePath.appending("Example"), + "Example", + configuration: configuration, + extraArgs: ["--traits", "default,Package9,Package10"], + buildSystem: buildSystem, + ) + // We expect no warnings to be produced. Specifically no unused dependency warnings. + let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") + #expect(!stderr.contains(unusedDependencyRegex)) + #expect( + stdout == """ + Package1Library1 trait1 enabled + Package2Library1 trait2 enabled + Package3Library1 trait3 enabled + Package4Library1 trait1 disabled + Package10Library1 trait1 enabled + Package10Library1 trait2 enabled + Package10Library1 trait1 enabled + Package10Library1 trait2 enabled + Package10Library2 has been included. + DEFINE1 enabled + DEFINE2 disabled + DEFINE3 disabled + + """ + ) + } } when: { (ProcessInfo.hostOperatingSystem == .windows && (CiEnvironment.runningInSmokeTestPipeline || buildSystem == .swiftbuild)) } @@ -126,7 +132,8 @@ struct TraitTests { .tags( Tag.Feature.Command.Run, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func traits_whenTraitUnification_whenSecondTraitNotEnabled( buildSystem: BuildSystemProvider.Kind, @@ -138,30 +145,32 @@ struct TraitTests { """, isIntermittent: (ProcessInfo.hostOperatingSystem == .windows), ) { - try await fixture(name: "Traits") { fixturePath in - let (stdout, stderr) = try await executeSwiftRun( - fixturePath.appending("Example"), - "Example", - configuration: configuration, - extraArgs: ["--traits", "default,Package9"], - buildSystem: buildSystem, - ) - // We expect no warnings to be produced. Specifically no unused dependency warnings. - let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") - #expect(!stderr.contains(unusedDependencyRegex)) - #expect(stdout == """ - Package1Library1 trait1 enabled - Package2Library1 trait2 enabled - Package3Library1 trait3 enabled - Package4Library1 trait1 disabled - Package10Library1 trait1 enabled - Package10Library1 trait2 enabled - DEFINE1 enabled - DEFINE2 disabled - DEFINE3 disabled - - """) - } + try await fixture(name: "Traits") { fixturePath in + let (stdout, stderr) = try await executeSwiftRun( + fixturePath.appending("Example"), + "Example", + configuration: configuration, + extraArgs: ["--traits", "default,Package9"], + buildSystem: buildSystem, + ) + // We expect no warnings to be produced. Specifically no unused dependency warnings. + let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") + #expect(!stderr.contains(unusedDependencyRegex)) + #expect( + stdout == """ + Package1Library1 trait1 enabled + Package2Library1 trait2 enabled + Package3Library1 trait3 enabled + Package4Library1 trait1 disabled + Package10Library1 trait1 enabled + Package10Library1 trait2 enabled + DEFINE1 enabled + DEFINE2 disabled + DEFINE3 disabled + + """ + ) + } } when: { (ProcessInfo.hostOperatingSystem == .windows && (CiEnvironment.runningInSmokeTestPipeline || buildSystem == .swiftbuild)) } @@ -174,7 +183,8 @@ struct TraitTests { .tags( Tag.Feature.Command.Run, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func traits_whenIndividualTraitsEnabled_andDefaultTraits( buildSystem: BuildSystemProvider.Kind, @@ -186,34 +196,36 @@ struct TraitTests { """, isIntermittent: (ProcessInfo.hostOperatingSystem == .windows), ) { - try await fixture(name: "Traits") { fixturePath in - let (stdout, stderr) = try await executeSwiftRun( - fixturePath.appending("Example"), - "Example", - configuration: configuration, - extraArgs: [ - "--traits", - "default,Package5,Package7,BuildCondition3", - ], - buildSystem: buildSystem, - ) - // We expect no warnings to be produced. Specifically no unused dependency warnings. - let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") - #expect(!stderr.contains(unusedDependencyRegex)) - #expect(stdout == """ - Package1Library1 trait1 enabled - Package2Library1 trait2 enabled - Package3Library1 trait3 enabled - Package4Library1 trait1 disabled - Package5Library1 trait1 enabled - Package6Library1 trait1 enabled - Package7Library1 trait1 disabled - DEFINE1 enabled - DEFINE2 disabled - DEFINE3 enabled - - """) - } + try await fixture(name: "Traits") { fixturePath in + let (stdout, stderr) = try await executeSwiftRun( + fixturePath.appending("Example"), + "Example", + configuration: configuration, + extraArgs: [ + "--traits", + "default,Package5,Package7,BuildCondition3", + ], + buildSystem: buildSystem, + ) + // We expect no warnings to be produced. Specifically no unused dependency warnings. + let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") + #expect(!stderr.contains(unusedDependencyRegex)) + #expect( + stdout == """ + Package1Library1 trait1 enabled + Package2Library1 trait2 enabled + Package3Library1 trait3 enabled + Package4Library1 trait1 disabled + Package5Library1 trait1 enabled + Package6Library1 trait1 enabled + Package7Library1 trait1 disabled + DEFINE1 enabled + DEFINE2 disabled + DEFINE3 enabled + + """ + ) + } } when: { (ProcessInfo.hostOperatingSystem == .windows && (CiEnvironment.runningInSmokeTestPipeline || buildSystem == .swiftbuild)) } @@ -226,31 +238,34 @@ struct TraitTests { .tags( Tag.Feature.Command.Run, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func traits_whenDefaultTraitsDisabled( buildSystem: BuildSystemProvider.Kind, configuration: BuildConfiguration, ) async throws { try await withKnownIssue(isIntermittent: (ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild)) { - try await fixture(name: "Traits") { fixturePath in - let (stdout, stderr) = try await executeSwiftRun( - fixturePath.appending("Example"), - "Example", - configuration: configuration, - extraArgs: ["--disable-default-traits"], - buildSystem: buildSystem, - ) - // We expect no warnings to be produced. Specifically no unused dependency warnings. - let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") - #expect(!stderr.contains(unusedDependencyRegex)) - #expect(stdout == """ - DEFINE1 disabled - DEFINE2 disabled - DEFINE3 disabled - - """) - } + try await fixture(name: "Traits") { fixturePath in + let (stdout, stderr) = try await executeSwiftRun( + fixturePath.appending("Example"), + "Example", + configuration: configuration, + extraArgs: ["--disable-default-traits"], + buildSystem: buildSystem, + ) + // We expect no warnings to be produced. Specifically no unused dependency warnings. + let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") + #expect(!stderr.contains(unusedDependencyRegex)) + #expect( + stdout == """ + DEFINE1 disabled + DEFINE2 disabled + DEFINE3 disabled + + """ + ) + } } when: { (ProcessInfo.hostOperatingSystem == .windows && (CiEnvironment.runningInSmokeTestPipeline || buildSystem == .swiftbuild)) } @@ -263,38 +278,42 @@ struct TraitTests { .tags( Tag.Feature.Command.Run, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func traits_whenIndividualTraitsEnabled_andDefaultTraitsDisabled( buildSystem: BuildSystemProvider.Kind, configuration: BuildConfiguration, ) async throws { - try await withKnownIssue(""" + try await withKnownIssue( + """ Windows: https://github.com/swiftlang/swift-build/issues/609 """, isIntermittent: (ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild), ) { - try await fixture(name: "Traits") { fixturePath in - let (stdout, stderr) = try await executeSwiftRun( - fixturePath.appending("Example"), - "Example", - configuration: configuration, - extraArgs: ["--traits", "Package5,Package7"], - buildSystem: buildSystem, - ) - // We expect no warnings to be produced. Specifically no unused dependency warnings. - let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") - #expect(!stderr.contains(unusedDependencyRegex)) - #expect(stdout == """ - Package5Library1 trait1 enabled - Package6Library1 trait1 enabled - Package7Library1 trait1 disabled - DEFINE1 disabled - DEFINE2 disabled - DEFINE3 disabled - - """) - } + try await fixture(name: "Traits") { fixturePath in + let (stdout, stderr) = try await executeSwiftRun( + fixturePath.appending("Example"), + "Example", + configuration: configuration, + extraArgs: ["--traits", "Package5,Package7"], + buildSystem: buildSystem, + ) + // We expect no warnings to be produced. Specifically no unused dependency warnings. + let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") + #expect(!stderr.contains(unusedDependencyRegex)) + #expect( + stdout == """ + Package5Library1 trait1 enabled + Package6Library1 trait1 enabled + Package7Library1 trait1 disabled + DEFINE1 disabled + DEFINE2 disabled + DEFINE3 disabled + + """ + ) + } } when: { (ProcessInfo.hostOperatingSystem == .windows && (CiEnvironment.runningInSmokeTestPipeline || buildSystem == .swiftbuild)) } @@ -307,7 +326,8 @@ struct TraitTests { .tags( Tag.Feature.Command.Run, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func traits_whenAllTraitsEnabled( buildSystem: BuildSystemProvider.Kind, @@ -319,37 +339,39 @@ struct TraitTests { """, isIntermittent: (ProcessInfo.hostOperatingSystem == .windows), ) { - try await fixture(name: "Traits") { fixturePath in - let (stdout, stderr) = try await executeSwiftRun( - fixturePath.appending("Example"), - "Example", - configuration: configuration, - extraArgs: ["--enable-all-traits"], - buildSystem: buildSystem, - ) - // We expect no warnings to be produced. Specifically no unused dependency warnings. - let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") - #expect(!stderr.contains(unusedDependencyRegex)) - #expect(stdout == """ - Package1Library1 trait1 enabled - Package2Library1 trait2 enabled - Package3Library1 trait3 enabled - Package4Library1 trait1 disabled - Package5Library1 trait1 enabled - Package6Library1 trait1 enabled - Package7Library1 trait1 disabled - Package10Library1 trait1 enabled - Package10Library1 trait2 enabled - Package10Library1 trait1 enabled - Package10Library1 trait2 enabled - Package10Library2 has been included. - Package10Library2 has been included. - DEFINE1 enabled - DEFINE2 enabled - DEFINE3 enabled - - """) - } + try await fixture(name: "Traits") { fixturePath in + let (stdout, stderr) = try await executeSwiftRun( + fixturePath.appending("Example"), + "Example", + configuration: configuration, + extraArgs: ["--enable-all-traits"], + buildSystem: buildSystem, + ) + // We expect no warnings to be produced. Specifically no unused dependency warnings. + let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") + #expect(!stderr.contains(unusedDependencyRegex)) + #expect( + stdout == """ + Package1Library1 trait1 enabled + Package2Library1 trait2 enabled + Package3Library1 trait3 enabled + Package4Library1 trait1 disabled + Package5Library1 trait1 enabled + Package6Library1 trait1 enabled + Package7Library1 trait1 disabled + Package10Library1 trait1 enabled + Package10Library1 trait2 enabled + Package10Library1 trait1 enabled + Package10Library1 trait2 enabled + Package10Library2 has been included. + Package10Library2 has been included. + DEFINE1 enabled + DEFINE2 enabled + DEFINE3 enabled + + """ + ) + } } when: { (ProcessInfo.hostOperatingSystem == .windows && (CiEnvironment.runningInSmokeTestPipeline || buildSystem == .swiftbuild)) } @@ -362,7 +384,8 @@ struct TraitTests { .tags( Tag.Feature.Command.Run, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func traits_whenAllTraitsEnabled_andDefaultTraitsDisabled( buildSystem: BuildSystemProvider.Kind, @@ -374,40 +397,42 @@ struct TraitTests { """, isIntermittent: (ProcessInfo.hostOperatingSystem == .windows) ) { - try await fixture(name: "Traits") { fixturePath in - let (stdout, stderr) = try await executeSwiftRun( - fixturePath.appending("Example"), - "Example", - configuration: configuration, - extraArgs: [ - "--enable-all-traits", - "--disable-default-traits", - ], - buildSystem: buildSystem, - ) - // We expect no warnings to be produced. Specifically no unused dependency warnings. - let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") - #expect(!stderr.contains(unusedDependencyRegex)) - #expect(stdout == """ - Package1Library1 trait1 enabled - Package2Library1 trait2 enabled - Package3Library1 trait3 enabled - Package4Library1 trait1 disabled - Package5Library1 trait1 enabled - Package6Library1 trait1 enabled - Package7Library1 trait1 disabled - Package10Library1 trait1 enabled - Package10Library1 trait2 enabled - Package10Library1 trait1 enabled - Package10Library1 trait2 enabled - Package10Library2 has been included. - Package10Library2 has been included. - DEFINE1 enabled - DEFINE2 enabled - DEFINE3 enabled - - """) - } + try await fixture(name: "Traits") { fixturePath in + let (stdout, stderr) = try await executeSwiftRun( + fixturePath.appending("Example"), + "Example", + configuration: configuration, + extraArgs: [ + "--enable-all-traits", + "--disable-default-traits", + ], + buildSystem: buildSystem, + ) + // We expect no warnings to be produced. Specifically no unused dependency warnings. + let unusedDependencyRegex = try Regex("warning: '.*': dependency '.*' is not used by any target") + #expect(!stderr.contains(unusedDependencyRegex)) + #expect( + stdout == """ + Package1Library1 trait1 enabled + Package2Library1 trait2 enabled + Package3Library1 trait3 enabled + Package4Library1 trait1 disabled + Package5Library1 trait1 enabled + Package6Library1 trait1 enabled + Package7Library1 trait1 disabled + Package10Library1 trait1 enabled + Package10Library1 trait2 enabled + Package10Library1 trait1 enabled + Package10Library1 trait2 enabled + Package10Library2 has been included. + Package10Library2 has been included. + DEFINE1 enabled + DEFINE2 enabled + DEFINE3 enabled + + """ + ) + } } when: { (ProcessInfo.hostOperatingSystem == .windows && (CiEnvironment.runningInSmokeTestPipeline || buildSystem == .swiftbuild)) } @@ -417,7 +442,8 @@ struct TraitTests { .tags( Tag.Feature.Command.Package.DumpPackage, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func traits_dumpPackage( buildSystem: BuildSystemProvider.Kind, @@ -444,31 +470,32 @@ struct TraitTests { .tags( Tag.Feature.Command.Test, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func tests_whenNoFlagPassed( buildSystem: BuildSystemProvider.Kind, configuration: BuildConfiguration, ) async throws { try await withKnownIssue { - try await fixture(name: "Traits") { fixturePath in - let (stdout, _) = try await executeSwiftTest( - fixturePath.appending("Example"), - configuration: configuration, - buildSystem: buildSystem, - ) - let expectedOut = """ - Package1Library1 trait1 enabled - Package2Library1 trait2 enabled - Package3Library1 trait3 enabled - Package4Library1 trait1 disabled - DEFINE1 enabled - DEFINE2 disabled - DEFINE3 disabled - - """ - #expect(stdout.contains(expectedOut)) - } + try await fixture(name: "Traits") { fixturePath in + let (stdout, _) = try await executeSwiftTest( + fixturePath.appending("Example"), + configuration: configuration, + buildSystem: buildSystem, + ) + let expectedOut = """ + Package1Library1 trait1 enabled + Package2Library1 trait2 enabled + Package3Library1 trait3 enabled + Package4Library1 trait1 disabled + DEFINE1 enabled + DEFINE2 disabled + DEFINE3 disabled + + """ + #expect(stdout.contains(expectedOut)) + } } when: { (buildSystem == .swiftbuild && [.windows].contains(ProcessInfo.hostOperatingSystem)) } @@ -479,7 +506,8 @@ struct TraitTests { .tags( Tag.Feature.Command.Test, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func tests_whenAllTraitsEnabled_andDefaultTraitsDisabled( buildSystem: BuildSystemProvider.Kind, @@ -502,22 +530,22 @@ struct TraitTests { buildSystem: buildSystem, ) let expectedOut = """ - Package1Library1 trait1 enabled - Package2Library1 trait2 enabled - Package3Library1 trait3 enabled - Package4Library1 trait1 disabled - Package5Library1 trait1 enabled - Package6Library1 trait1 enabled - Package7Library1 trait1 disabled - Package10Library1 trait1 enabled - Package10Library1 trait2 enabled - Package10Library1 trait1 enabled - Package10Library1 trait2 enabled - DEFINE1 enabled - DEFINE2 enabled - DEFINE3 enabled - - """ + Package1Library1 trait1 enabled + Package2Library1 trait2 enabled + Package3Library1 trait3 enabled + Package4Library1 trait1 disabled + Package5Library1 trait1 enabled + Package6Library1 trait1 enabled + Package7Library1 trait1 disabled + Package10Library1 trait1 enabled + Package10Library1 trait2 enabled + Package10Library1 trait1 enabled + Package10Library1 trait2 enabled + DEFINE1 enabled + DEFINE2 enabled + DEFINE3 enabled + + """ #expect(stdout.contains(expectedOut), "got stdout: '\(stdout)'\nstderr: '\(stderr)'") } } when: { @@ -529,34 +557,39 @@ struct TraitTests { .tags( Tag.Feature.Command.Package.DumpSymbolGraph, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func packageDumpSymbolGraph_enablesAllTraits( buildSystem: BuildSystemProvider.Kind, configuration: BuildConfiguration, ) async throws { - try await withKnownIssue(isIntermittent: true, { - try await fixture(name: "Traits") { fixturePath in - let (stdout, _) = try await executeSwiftPackage( - fixturePath.appending("Package10"), - configuration: configuration, - extraArgs: ["dump-symbol-graph"], - buildSystem: buildSystem, - ) - let optionalPath = stdout - .lazy - .split(whereSeparator: \.isNewline) - .first { String($0).hasPrefix("Files written to ") }? - .dropFirst(17) - - let path = try String(#require(optionalPath)) - let symbolGraph = try String(contentsOfFile: "\(path)/Package10Library1.symbols.json", encoding: .utf8) - #expect(symbolGraph.contains("TypeGatedByPackage10Trait1")) - #expect(symbolGraph.contains("TypeGatedByPackage10Trait2")) + try await withKnownIssue( + isIntermittent: true, + { + try await fixture(name: "Traits") { fixturePath in + let (stdout, _) = try await executeSwiftPackage( + fixturePath.appending("Package10"), + configuration: configuration, + extraArgs: ["dump-symbol-graph"], + buildSystem: buildSystem, + ) + let optionalPath = stdout + .lazy + .split(whereSeparator: \.isNewline) + .first { String($0).hasPrefix("Files written to ") }? + .dropFirst(17) + + let path = try String(#require(optionalPath)) + let symbolGraph = try String(contentsOfFile: "\(path)/Package10Library1.symbols.json", encoding: .utf8) + #expect(symbolGraph.contains("TypeGatedByPackage10Trait1")) + #expect(symbolGraph.contains("TypeGatedByPackage10Trait2")) + } + }, + when: { + ProcessInfo.hostOperatingSystem == .windows } - }, when: { - ProcessInfo.hostOperatingSystem == .windows - }) + ) } @Test( @@ -564,12 +597,13 @@ struct TraitTests { .tags( Tag.Feature.Command.Package.Plugin, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func packagePluginGetSymbolGraph_enablesAllTraits( buildSystem: BuildSystemProvider.Kind, configuration: BuildConfiguration, - ) async throws { + ) async throws { try await withKnownIssue(isIntermittent: true) { try await fixture(name: "Traits") { fixturePath in // The swiftbuild build system doesn't yet have the ability for command plugins to request symbol graphs @@ -607,7 +641,8 @@ struct TraitTests { .tags( Tag.Feature.Command.Run, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func packageDisablingDefaultsTrait_whenNoTraits( buildSystem: BuildSystemProvider.Kind, @@ -616,7 +651,7 @@ struct TraitTests { try await fixture(name: "Traits") { fixturePath in let error = await #expect(throws: SwiftPMError.self) { try await executeSwiftRun( - fixturePath.appending("DisablingEmptyDefaultsExample"), + fixturePath.appending("DisablingEmptyDefaultsExample"), "DisablingEmptyDefaultsExample", configuration: configuration, buildSystem: buildSystem, @@ -642,39 +677,42 @@ struct TraitTests { Tag.Feature.Command.Run, ), arguments: - getBuildData(for: SupportedBuildSystemOnAllPlatforms), + getBuildData(for: SupportedBuildSystemOnAllPlatforms), getTraitCombinations( - ("ExtraTrait", - """ - Package10Library2 has been included. - DEFINE1 disabled - DEFINE2 disabled - DEFINE3 disabled - - """ + ( + "ExtraTrait", + """ + Package10Library2 has been included. + DEFINE1 disabled + DEFINE2 disabled + DEFINE3 disabled + + """ ), - ("Package10", - """ - Package10Library1 trait1 disabled - Package10Library1 trait2 enabled - Package10Library2 has been included. - DEFINE1 disabled - DEFINE2 disabled - DEFINE3 disabled - - """ + ( + "Package10", + """ + Package10Library1 trait1 disabled + Package10Library1 trait2 enabled + Package10Library2 has been included. + DEFINE1 disabled + DEFINE2 disabled + DEFINE3 disabled + + """ ), - ("ExtraTrait,Package10", - """ - Package10Library1 trait1 disabled - Package10Library1 trait2 enabled - Package10Library2 has been included. - Package10Library2 has been included. - DEFINE1 disabled - DEFINE2 disabled - DEFINE3 disabled - - """ + ( + "ExtraTrait,Package10", + """ + Package10Library1 trait1 disabled + Package10Library1 trait2 enabled + Package10Library2 has been included. + Package10Library2 has been included. + DEFINE1 disabled + DEFINE2 disabled + DEFINE3 disabled + + """ ) ) ) diff --git a/Tests/FunctionalTests/VersionSpecificTests.swift b/Tests/FunctionalTests/VersionSpecificTests.swift index e60443390b3..b8aee4f9f16 100644 --- a/Tests/FunctionalTests/VersionSpecificTests.swift +++ b/Tests/FunctionalTests/VersionSpecificTests.swift @@ -27,142 +27,143 @@ import enum PackageModel.BuildConfiguration struct VersionSpecificTests { /// Functional tests of end-to-end support for version specific dependency resolution. @Test( - .issue("https://github.com/swiftlang/swift-tools-support-core/pull/521", relationship: .fixedBy), // long file path issue + .issue("https://github.com/swiftlang/swift-tools-support-core/pull/521", relationship: .fixedBy), // long file path issue .tags( .Feature.Command.Build, .Feature.Command.Package.Reset, .Feature.Version, ), - arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases, + arguments: SupportedBuildSystemOnAllPlatforms, + BuildConfiguration.allCases, ) func endToEndResolution( buildSystem: BuildSystemProvider.Kind, configuration: BuildConfiguration, ) async throws { - try await withKnownIssue(isIntermittent: true) { // Test passed on Windows at-desk - try await testWithTemporaryDirectory{ path in - let fs = localFileSystem + try await withKnownIssue(isIntermittent: true) { // Test passed on Windows at-desk + try await testWithTemporaryDirectory { path in + let fs = localFileSystem - // Create a repo for the dependency to test against. - let depPath = path.appending("Dep") - try fs.createDirectory(depPath) - initGitRepo(depPath) - let repo = GitRepository(path: depPath) + // Create a repo for the dependency to test against. + let depPath = path.appending("Dep") + try fs.createDirectory(depPath) + initGitRepo(depPath) + let repo = GitRepository(path: depPath) - // Create the initial commit. - try fs.writeFileContents( - depPath.appending("Package.swift"), - string: """ - // swift-tools-version:4.2 - import PackageDescription - let package = Package( - name: "Dep", - products: [ - .library(name: "Dep", targets: ["Dep"]), - ], - targets: [ - .target(name: "Dep", path: "./") - ] - ) - """ - ) - try repo.stage(file: "Package.swift") - try repo.commit(message: "Initial") - try repo.tag(name: "1.0.0") + // Create the initial commit. + try fs.writeFileContents( + depPath.appending("Package.swift"), + string: """ + // swift-tools-version:4.2 + import PackageDescription + let package = Package( + name: "Dep", + products: [ + .library(name: "Dep", targets: ["Dep"]), + ], + targets: [ + .target(name: "Dep", path: "./") + ] + ) + """ + ) + try repo.stage(file: "Package.swift") + try repo.commit(message: "Initial") + try repo.tag(name: "1.0.0") - // Create the version to test against. - try fs.writeFileContents( - depPath.appending("Package.swift"), - // FIXME: We end up filtering this manifest if it has an invalid - // tools version as they're assumed to be v3 manifests. Should we - // do something better? - string: """ - // swift-tools-version:4.2 - NOT_A_VALID_PACKAGE - """ - ) - try fs.writeFileContents( - depPath.appending("foo.swift"), - string: """ - public func foo() { print("foo\\n") } - """ - ) - try repo.stage(file: "Package.swift") - try repo.stage(file: "foo.swift") - try repo.commit(message: "Bogus v1.1.0") - try repo.tag(name: "1.1.0") + // Create the version to test against. + try fs.writeFileContents( + depPath.appending("Package.swift"), + // FIXME: We end up filtering this manifest if it has an invalid + // tools version as they're assumed to be v3 manifests. Should we + // do something better? + string: """ + // swift-tools-version:4.2 + NOT_A_VALID_PACKAGE + """ + ) + try fs.writeFileContents( + depPath.appending("foo.swift"), + string: """ + public func foo() { print("foo\\n") } + """ + ) + try repo.stage(file: "Package.swift") + try repo.stage(file: "foo.swift") + try repo.commit(message: "Bogus v1.1.0") + try repo.tag(name: "1.1.0") - // Create the primary repository. - let primaryPath = path.appending("Primary") - try fs.createDirectory(primaryPath, recursive: true) - try fs.writeFileContents( - primaryPath.appending("Package.swift"), - string: """ - // swift-tools-version:4.2 - import PackageDescription - let package = Package( - name: "Primary", - dependencies: [ - .package(url: "../Dep", from: "1.0.0"), - ], - targets: [ - .target(name: "Primary", dependencies: ["Dep"], path: "./") - ] + // Create the primary repository. + let primaryPath = path.appending("Primary") + try fs.createDirectory(primaryPath, recursive: true) + try fs.writeFileContents( + primaryPath.appending("Package.swift"), + string: """ + // swift-tools-version:4.2 + import PackageDescription + let package = Package( + name: "Primary", + dependencies: [ + .package(url: "../Dep", from: "1.0.0"), + ], + targets: [ + .target(name: "Primary", dependencies: ["Dep"], path: "./") + ] + ) + """ + ) + // This build should fail, because of the invalid package. + await #expect(throws: (any Error).self) { + try await executeSwiftBuild( + primaryPath, + configuration: configuration, + buildSystem: buildSystem, ) - """ - ) - // This build should fail, because of the invalid package. - await #expect(throws: (any Error).self) { + } + + // Create a file which requires a version 1.1.0 resolution. + try fs.writeFileContents( + primaryPath.appending("main.swift"), + string: """ + import Dep + Dep.foo() + """ + ) + + // Create a version-specific tag, which should work. + try fs.writeFileContents( + depPath.appending("Package.swift"), + string: """ + // swift-tools-version:4.2 + import PackageDescription + let package = Package( + name: "Dep", + products: [ + .library(name: "Dep", targets: ["Dep"]), + ], + targets: [ + .target(name: "Dep", path: "./") + ] + ) + """ + ) + try repo.stage(file: "Package.swift") + try repo.commit(message: "OK v1.1.0") + try repo.tag(name: "1.1.0@swift-\(SwiftVersion.current.major)") + + // The build should work now. + _ = try await executeSwiftPackage( + primaryPath, + configuration: configuration, + extraArgs: ["reset"], + buildSystem: buildSystem, + ) try await executeSwiftBuild( primaryPath, configuration: configuration, buildSystem: buildSystem, ) } - - // Create a file which requires a version 1.1.0 resolution. - try fs.writeFileContents( - primaryPath.appending("main.swift"), - string: """ - import Dep - Dep.foo() - """ - ) - - // Create a version-specific tag, which should work. - try fs.writeFileContents( - depPath.appending("Package.swift"), - string: """ - // swift-tools-version:4.2 - import PackageDescription - let package = Package( - name: "Dep", - products: [ - .library(name: "Dep", targets: ["Dep"]), - ], - targets: [ - .target(name: "Dep", path: "./") - ] - ) - """ - ) - try repo.stage(file: "Package.swift") - try repo.commit(message: "OK v1.1.0") - try repo.tag(name: "1.1.0@swift-\(SwiftVersion.current.major)") - - // The build should work now. - _ = try await executeSwiftPackage( - primaryPath, - configuration: configuration, - extraArgs: ["reset"], - buildSystem: buildSystem, - ) - try await executeSwiftBuild( - primaryPath, - configuration: configuration, - buildSystem: buildSystem, - ) - } } when: { buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows && CiEnvironment.runningInSelfHostedPipeline } diff --git a/Tests/IntegrationTests/BasicTests.swift b/Tests/IntegrationTests/BasicTests.swift index a7ed24883f7..4473943bd18 100644 --- a/Tests/IntegrationTests/BasicTests.swift +++ b/Tests/IntegrationTests/BasicTests.swift @@ -62,7 +62,8 @@ private struct BasicTests { // Verify that the app works. let dealerOutput = try sh( - AbsolutePath(validating: ".build/debug/dealer", relativeTo: packagePath), "10" + AbsolutePath(validating: ".build/debug/dealer", relativeTo: packagePath), + "10" ).stdout #expect(dealerOutput.filter(\.isPlayingCardSuit).count == 10) @@ -98,16 +99,16 @@ private struct BasicTests { packagePath.appending(component: "Package.swift"), bytes: ByteString( encodingAsUTF8: """ - // swift-tools-version:4.2 - import PackageDescription - - let package = Package( - name: "tool", - targets: [ - .target(name: "tool", path: "./"), - ] - ) - """ + // swift-tools-version:4.2 + import PackageDescription + + let package = Package( + name: "tool", + targets: [ + .target(name: "tool", path: "./"), + ] + ) + """ ) ) try localFileSystem.writeFileContents( @@ -144,7 +145,7 @@ private struct BasicTests { try localFileSystem.createDirectory(packagePath) try await executeSwiftPackage( packagePath, - extraArgs: ["init", "--type", "executable"], + extraArgs: ["init", "--type", "executable"], buildSystem: .native, ) let packageOutput = try await executeSwiftBuild( @@ -282,16 +283,16 @@ private struct BasicTests { packagePath.appending(component: "Package.swift"), bytes: ByteString( encodingAsUTF8: """ - // swift-tools-version:4.2 - import PackageDescription - - let package = Package( - name: "special tool", - targets: [ - .target(name: "special tool", path: "./"), - ] - ) - """ + // swift-tools-version:4.2 + import PackageDescription + + let package = Package( + name: "special tool", + targets: [ + .target(name: "special tool", path: "./"), + ] + ) + """ ) ) try localFileSystem.writeFileContents( @@ -309,10 +310,9 @@ private struct BasicTests { extraArgs: ["-v"], buildSystem: .native, ).stdout - let expression = ProcessInfo - .hostOperatingSystem != .windows ? - #/swiftc.* -module-name special_tool .* '@.*/more spaces/special tool/.build/[^/]+/debug/special_tool.build/sources'/# : - #/swiftc.* -module-name special_tool .* "@.*\\more spaces\\special tool\\.build\\[^\\]+\\debug\\special_tool.build\\sources"/# + let expression = + ProcessInfo + .hostOperatingSystem != .windows ? #/swiftc.* -module-name special_tool .* '@.*/more spaces/special tool/.build/[^/]+/debug/special_tool.build/sources'/# : #/swiftc.* -module-name special_tool .* "@.*\\more spaces\\special tool\\.build\\[^\\]+\\debug\\special_tool.build\\sources"/# #expect(try expression.firstMatch(in: buildOutput) != nil) #expect(buildOutput.contains("Build complete")) @@ -353,13 +353,15 @@ private struct BasicTests { packagePath.appending(components: "Sources", "secho.swift"), bytes: ByteString( encodingAsUTF8: """ - import Foundation - print(CommandLine.arguments.dropFirst().joined(separator: " ")) - """ + import Foundation + print(CommandLine.arguments.dropFirst().joined(separator: " ")) + """ ) ) let result = try await executeSwiftRun( - packagePath, "secho", extraArgs: [ "1", #""two""#], + packagePath, + "secho", + extraArgs: ["1", #""two""#], buildSystem: .native, ) @@ -367,8 +369,8 @@ private struct BasicTests { let compilingRegex = try Regex("Compiling .*secho.*") let linkingRegex = try Regex("Linking .*secho") #expect(result.stdout.contains(compilingRegex), "stdout: '\(result.stdout)'\n stderr:'\(result.stderr)'") - #expect(result.stdout.contains(linkingRegex), "stdout: '\(result.stdout)'\n stderr:'\(result.stderr)'") - #expect(result.stdout.contains("Build of product 'secho' complete"), "stdout: '\(result.stdout)'\n stderr:'\(result.stderr)'") + #expect(result.stdout.contains(linkingRegex), "stdout: '\(result.stdout)'\n stderr:'\(result.stderr)'") + #expect(result.stdout.contains("Build of product 'secho' complete"), "stdout: '\(result.stdout)'\n stderr:'\(result.stderr)'") #expect(result.stdout == "1 \"two\"\(ProcessInfo.EOL)") @@ -395,18 +397,18 @@ private struct BasicTests { packagePath.appending(components: "Tests", "swiftTestTests", "MyTests.swift"), bytes: ByteString( encodingAsUTF8: """ - import XCTest - - final class MyTests: XCTestCase { - func testFoo() { - XCTAssertTrue(1 == 1) - } - func testBar() { - XCTAssertFalse(1 == 2) + import XCTest + + final class MyTests: XCTestCase { + func testFoo() { + XCTAssertTrue(1 == 1) + } + func testBar() { + XCTAssertFalse(1 == 2) + } + func testBaz() { } } - func testBaz() { } - } - """ + """ ) ) let result = try await executeSwiftTest( diff --git a/Tests/IntegrationTests/SwiftPMTests.swift b/Tests/IntegrationTests/SwiftPMTests.swift index b8cf10ecc85..657fa140053 100644 --- a/Tests/IntegrationTests/SwiftPMTests.swift +++ b/Tests/IntegrationTests/SwiftPMTests.swift @@ -32,10 +32,10 @@ private struct SwiftPMTests { #expect(!runOutput.stderr.contains("error:")) #expect( runOutput.stdout == """ - SwiftFramework() - Library(framework: SwiftFramework.SwiftFramework()) - - """ + SwiftFramework() + Library(framework: SwiftFramework.SwiftFramework()) + + """ ) } @@ -71,7 +71,7 @@ private struct SwiftPMTests { ) #expect( packageOutput.stdout.spm_chomp() - == "d1f202b1bfe04dea30b2bc4038f8059dcd75a5a176f1d81fcaedb6d3597d1158" + == "d1f202b1bfe04dea30b2bc4038f8059dcd75a5a176f1d81fcaedb6d3597d1158" ) } } @@ -154,7 +154,7 @@ private struct SwiftPMTests { @Test(.requireHostOS(.macOS), arguments: [BuildSystemProvider.Kind.native, .swiftbuild]) func testArchCustomization(buildSystem: BuildSystemProvider.Kind) async throws { - try await withTemporaryDirectory { tmpDir in + try await withTemporaryDirectory { tmpDir in let packagePath = tmpDir.appending(component: "foo") try localFileSystem.createDirectory(packagePath) try await executeSwiftPackage( @@ -212,16 +212,17 @@ private struct SwiftPMTests { let fooPath: AbsolutePath let hostArch: String #if arch(x86_64) - hostArch = "x86_64" + hostArch = "x86_64" #elseif arch(arm64) - hostArch = "arm64" + hostArch = "arm64" #else - precondition("Unsupported platform or host arch for test") + precondition("Unsupported platform or host arch for test") #endif switch buildSystem { case .native: fooPath = try AbsolutePath( - validating: ".build/apple/Products/Debug/foo", relativeTo: packagePath + validating: ".build/apple/Products/Debug/foo", + relativeTo: packagePath ) case .swiftbuild: fooPath = try AbsolutePath( @@ -275,26 +276,26 @@ private struct SwiftPMTests { try localFileSystem.writeFileContents( AbsolutePath(validating: "Tests/ReproTests/Subject.swift", relativeTo: packagePath), string: """ - struct Subject { - static func a() { _ = "a" } - static func b() { _ = "b" } - } - """ + struct Subject { + static func a() { _ = "a" } + static func b() { _ = "b" } + } + """ ) try localFileSystem.writeFileContents( AbsolutePath(validating: "Tests/ReproTests/ReproTests.swift", relativeTo: packagePath), string: """ - import Testing - import class Foundation.ProcessInfo - @Suite struct Suite { - @Test func testProfilePathCanary() throws { - let pattern = try #require(ProcessInfo.processInfo.environment["LLVM_PROFILE_FILE"]) - #expect(pattern.hasSuffix(".%p.profraw")) + import Testing + import class Foundation.ProcessInfo + @Suite struct Suite { + @Test func testProfilePathCanary() throws { + let pattern = try #require(ProcessInfo.processInfo.environment["LLVM_PROFILE_FILE"]) + #expect(pattern.hasSuffix(".%p.profraw")) + } + @Test func testA() async { await #expect(processExitsWith: .success) { Subject.a() } } + @Test func testB() async { await #expect(processExitsWith: .success) { Subject.b() } } } - @Test func testA() async { await #expect(processExitsWith: .success) { Subject.a() } } - @Test func testB() async { await #expect(processExitsWith: .success) { Subject.b() } } - } - """ + """ ) let expectedCoveragePath = try await executeSwiftTest( packagePath, diff --git a/Tests/IntegrationTests/XCBuildTests.swift b/Tests/IntegrationTests/XCBuildTests.swift index c6bd4faa4d7..a079060c1b1 100644 --- a/Tests/IntegrationTests/XCBuildTests.swift +++ b/Tests/IntegrationTests/XCBuildTests.swift @@ -213,7 +213,7 @@ private struct XCBuildTests { try await executeSwiftBuild( fooPath, extraArgs: [ - "--build-tests", + "--build-tests" ], buildSystem: .xcode, ) @@ -227,7 +227,7 @@ private struct XCBuildTests { fooPath, configuration: .release, extraArgs: [ - "--build-tests", + "--build-tests" ], buildSystem: .xcode, ) @@ -521,9 +521,9 @@ private struct XCBuildTests { do { let output = try await executeSwiftTest( - fooPath, + fooPath, extraArgs: ["--parallel"], - buildSystem: .xcode, + buildSystem: .xcode, ) #expect(output.stdout.contains("Testing FooTests")) #expect(output.stdout.contains("Testing CFooTests")) diff --git a/Tests/LLBuildManifestTests/LLBuildManifestTests.swift b/Tests/LLBuildManifestTests/LLBuildManifestTests.swift index 9e7e822248b..296c14c6926 100644 --- a/Tests/LLBuildManifestTests/LLBuildManifestTests.swift +++ b/Tests/LLBuildManifestTests/LLBuildManifestTests.swift @@ -36,7 +36,7 @@ final class LLBuildManifestTests: XCTestCase { let commandName = outputPath.pathString XCTAssertEqual(manifest.commands.count, 1) - + let command = try XCTUnwrap(manifest.commands[commandName]?.tool as? WriteAuxiliaryFile) XCTAssertEqual(command, .init(inputs: inputs, outputFilePath: outputPath)) @@ -67,7 +67,9 @@ final class LLBuildManifestTests: XCTestCase { // FIXME(#5475) - use the platform's preferred separator for directory // indicators - XCTAssertEqual(contents.replacingOccurrences(of: "\\\\", with: "\\"), """ + XCTAssertEqual( + contents.replacingOccurrences(of: "\\\\", with: "\\"), + """ client: name: basic file-system: device-agnostic @@ -86,7 +88,8 @@ final class LLBuildManifestTests: XCTestCase { outputs: [""] - """) + """ + ) } func testShellCommands() throws { @@ -105,7 +108,7 @@ final class LLBuildManifestTests: XCTestCase { .file(root.appending(components: "file.out")) ], arguments: [ - "foo", "bar", "baz" + "foo", "bar", "baz", ], environment: [ "ABC": "DEF", @@ -122,7 +125,9 @@ final class LLBuildManifestTests: XCTestCase { let contents: String = try fs.readFileContents("/manifest.yaml") - XCTAssertEqual(contents.replacingOccurrences(of: "\\\\", with: "\\"), """ + XCTAssertEqual( + contents.replacingOccurrences(of: "\\\\", with: "\\"), + """ client: name: basic file-system: device-agnostic @@ -144,7 +149,8 @@ final class LLBuildManifestTests: XCTestCase { allow-missing-inputs: true - """) + """ + ) } func testMutatedNodes() throws { @@ -164,7 +170,7 @@ final class LLBuildManifestTests: XCTestCase { ], outputs: [mutatedNode, createTimestampNode], arguments: [ - "cp", "file.in", "file.out" + "cp", "file.in", "file.out", ] ) @@ -178,7 +184,7 @@ final class LLBuildManifestTests: XCTestCase { .virtual("C.mutate") ], arguments: [ - "touch", "file.out" + "touch", "file.out", ] ) @@ -187,7 +193,9 @@ final class LLBuildManifestTests: XCTestCase { let contents: String = try fs.readFileContents("/manifest.yaml") - XCTAssertEqual(contents.replacingOccurrences(of: "\\\\", with: "\\"), """ + XCTAssertEqual( + contents.replacingOccurrences(of: "\\\\", with: "\\"), + """ client: name: basic file-system: device-agnostic @@ -215,7 +223,8 @@ final class LLBuildManifestTests: XCTestCase { description: "C.mutate" args: ["touch","file.out"] - - """) + + """ + ) } } diff --git a/Tests/PackageCollectionsModelTests/PackageCollectionModelTests.swift b/Tests/PackageCollectionsModelTests/PackageCollectionModelTests.swift index 0eba1793424..4da0aa194c3 100644 --- a/Tests/PackageCollectionsModelTests/PackageCollectionModelTests.swift +++ b/Tests/PackageCollectionsModelTests/PackageCollectionModelTests.swift @@ -37,7 +37,7 @@ class PackageCollectionModelTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: [.init(name: "macOS", version: "10.15")] - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: [Model.Compatibility(platform: Model.Platform(name: "macOS"), swiftVersion: "5.2")], @@ -50,11 +50,11 @@ class PackageCollectionModelTests: XCTestCase { organizationName: "Appleseed Inc." ), createdAt: Date() - ), + ) ], readmeURL: "https://package-collection-tests.com/repos/foobar/README", license: .init(name: "Apache-2.0", url: "https://package-collection-tests.com/repos/foobar/LICENSE") - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", @@ -90,7 +90,7 @@ class PackageCollectionModelTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: [.init(name: "macOS", version: "10.15")] - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: [Model.Compatibility(platform: Model.Platform(name: "macOS"), swiftVersion: "5.2")], @@ -103,11 +103,11 @@ class PackageCollectionModelTests: XCTestCase { organizationName: "Appleseed Inc." ), createdAt: Date() - ), + ) ], readmeURL: "https://package-collection-tests.com/repos/foobar/README", license: .init(name: "Apache-2.0", url: "https://package-collection-tests.com/repos/foobar/LICENSE") - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", diff --git a/Tests/PackageCollectionsSigningTests/CertificatePolicyTests.swift b/Tests/PackageCollectionsSigningTests/CertificatePolicyTests.swift index e5d4abdcf7b..6b3614a5315 100644 --- a/Tests/PackageCollectionsSigningTests/CertificatePolicyTests.swift +++ b/Tests/PackageCollectionsSigningTests/CertificatePolicyTests.swift @@ -78,7 +78,7 @@ class CertificatePolicyTests: XCTestCase { func test_validate_revoked() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif let certChain = try await self.readTestCertChain( @@ -111,7 +111,7 @@ class CertificatePolicyTests: XCTestCase { func test_validate_defaultPolicy() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif let certChain = try await self.readTestCertChain( @@ -171,7 +171,7 @@ class CertificatePolicyTests: XCTestCase { func test_validate_appleSwiftPackageCollectionPolicy_rsa() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif let certChain = try await self.readTestCertChain( @@ -231,7 +231,7 @@ class CertificatePolicyTests: XCTestCase { func test_validate_appleSwiftPackageCollectionPolicy_ec() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif let certChain = try await self.readTestCertChain( @@ -291,7 +291,7 @@ class CertificatePolicyTests: XCTestCase { func test_validate_defaultPolicy_user() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif let certChain = try await self.readTestCertChain( @@ -376,7 +376,7 @@ class CertificatePolicyTests: XCTestCase { func test_validate_appleSwiftPackageCollectionPolicy_rsa_user() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif let certChain = try await self.readTestCertChain( @@ -461,7 +461,7 @@ class CertificatePolicyTests: XCTestCase { func test_validate_appleSwiftPackageCollectionPolicy_ec_user() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif let certChain = try await self.readTestCertChain( diff --git a/Tests/PackageCollectionsSigningTests/PackageCollectionSigningTests.swift b/Tests/PackageCollectionsSigningTests/PackageCollectionSigningTests.swift index 89ed50aacc1..b881609208f 100644 --- a/Tests/PackageCollectionsSigningTests/PackageCollectionSigningTests.swift +++ b/Tests/PackageCollectionsSigningTests/PackageCollectionSigningTests.swift @@ -229,7 +229,7 @@ class PackageCollectionSigningTests: XCTestCase { func test_signAndValidate_defaultPolicy() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif try await withTemporaryDirectory { tmp in @@ -322,7 +322,7 @@ class PackageCollectionSigningTests: XCTestCase { func test_signAndValidate_appleSwiftPackageCollectionPolicy_rsa() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif try await withTemporaryDirectory { tmp in @@ -415,7 +415,7 @@ class PackageCollectionSigningTests: XCTestCase { func test_signAndValidate_appleSwiftPackageCollectionPolicy_ec() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif try await withTemporaryDirectory { tmp in @@ -508,7 +508,7 @@ class PackageCollectionSigningTests: XCTestCase { func test_signAndValidate_defaultPolicy_user() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif try await withTemporaryDirectory { tmp in @@ -573,7 +573,7 @@ class PackageCollectionSigningTests: XCTestCase { func test_signAndValidate_appleSwiftPackageCollectionPolicy_rsa_user() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif try await withTemporaryDirectory { tmp in @@ -640,7 +640,7 @@ class PackageCollectionSigningTests: XCTestCase { func test_signAndValidate_appleSwiftPackageCollectionPolicy_ec_user() async throws { #if ENABLE_REAL_CERT_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif try await withTemporaryDirectory { tmp in diff --git a/Tests/PackageCollectionsSigningTests/Utilities.swift b/Tests/PackageCollectionsSigningTests/Utilities.swift index 470f9448094..885bb753e8d 100644 --- a/Tests/PackageCollectionsSigningTests/Utilities.swift +++ b/Tests/PackageCollectionsSigningTests/Utilities.swift @@ -71,96 +71,96 @@ struct TestCertificatePolicy: CertificatePolicy { // MARK: - Test keys let ecPrivateKey = """ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIMFnwA1gjIFnFZim4B2QvoXJIG2L4B8nH1BBZFlotA24oAoGCCqGSM49 -AwEHoUQDQgAEkc2FgXZVz9llhV6+jAGPVHEcxBxK5tui9HWzvtE+ogKPr7i3e2JO -Xwm91hecppS11y/S8bLmrFxA+dCP/V7bnw== ------END EC PRIVATE KEY----- -""" + -----BEGIN EC PRIVATE KEY----- + MHcCAQEEIMFnwA1gjIFnFZim4B2QvoXJIG2L4B8nH1BBZFlotA24oAoGCCqGSM49 + AwEHoUQDQgAEkc2FgXZVz9llhV6+jAGPVHEcxBxK5tui9HWzvtE+ogKPr7i3e2JO + Xwm91hecppS11y/S8bLmrFxA+dCP/V7bnw== + -----END EC PRIVATE KEY----- + """ let ecPublicKey = """ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkc2FgXZVz9llhV6+jAGPVHEcxBxK -5tui9HWzvtE+ogKPr7i3e2JOXwm91hecppS11y/S8bLmrFxA+dCP/V7bnw== ------END PUBLIC KEY----- -""" + -----BEGIN PUBLIC KEY----- + MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkc2FgXZVz9llhV6+jAGPVHEcxBxK + 5tui9HWzvtE+ogKPr7i3e2JOXwm91hecppS11y/S8bLmrFxA+dCP/V7bnw== + -----END PUBLIC KEY----- + """ let rsaPrivateKey = """ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEAoQIWz/MQ+mRShQxxxs+zlCLHRz+R1zUPKZhg3eggbXartfyI -OSPEDaVANCjE1QLg0dtGCpkbMAVQLkC7os5ZuW6A6qtSAU6WUBOvnDBPVumqmDUq -AeXGEQyDZqReRm3D4Ov4qOTlIk34pRhoCymaNTiw7GfyzzWOcPxcRGGTz6fv1gmS -wDnURBeL9QUAb2/sdAAsY/SZzziNF+womF8y3mn+IvlKL3EhtSxUfdZpPdFmxPza -oVIlllFQcKnxH4/0PZeyPK0Npq4kCqATXcYXmaa3Ms9tPcsQUggtAR/QepyrKmB1 -SRAouHqKi+bGTlCpFSFbDgW422gfqXEEboh39QIDAQABAoIBAQCRUR9hxFHYjF9m -MhsmgyPjWZhel+N7RypOMneLEQzjfy3vbONOHxe98R4HdZxhXN2oyq1mt1UwfDsn -48j2YiPdFv1H0CSNhW5pC7t9zqRtHyyXf7RQTh/8Fz0pkMR98GfQQ2oElcKwuYrn -ByYwnPXPf0E/vXoKxp2vIDXuidssmUl37mvbyppGaVl+Is6GmAiZkNOKN8ZEXPvz -4BivJ3yhs/RiM5RUF93qj8j/3P6R8rXLemAE9jrKjGG7Vv966p1Fh9+wNnnnbT8t -zLDUVwD7Q/JERr+3Wdecp+pZIfWTvJJhE8R3IM4WrLQNeUEKo7YovfYA7rah3gP/ -ixM2BM5pAoGBAM5+c7Sxl7hzII2yPxN2fIslyKw3E8HP1nnqUPUegFsU3TZRQUnZ -gm5JgQRPqFYy6fwouL07KdSb/zIes3ra/qkhaOewHsAvvvxKKM6FGqYrkb5BKv0s -gF/m4qg6GLSW3BVb/QfnwHdWE7z7KPGuomzg+pqshxTyKYkGN2l8IIu7AoGBAMeb -81636nRy62CYQhNCp13wqmmUJ8/VnNj2jdwdXQ5vlgQdrwFm2p52cEFn/AhL5WIn -GShRLKL/keK71tsD0hCsTuZISR1xFiFk0TFmjxSX+z2D9VGvSECtNfySRuroKorS -xIXsrx6dvk/Ef54yDus1O5vvdT3l6vSDbVJESFgPAoGBAIAFJ8kT/YNOZRVUOATi -Ba7jGvmiH+6d41OscMq3QU62rbr6P2cAofusOH+qvyvJ3wUFXht7raBxopK5M/7r -/MxwuTBDIZ13PIn/lDMNlIsHIhF5J6TUzTYn18gCVMTJbuMTJ9mZ1dpmlFAqyqSj -53FnPhdc9VaIGDYqk3ojia33AoGAd52bzNH3vMq1BJCZYANcWm4DIPu4k9JViKrP -Pe2WuzThOBw1qGhjb/xXrspKfQpGLnhxmfhzAEaYvL+FtH9onbc0HMmKjwsakO5i -cfEcouGknCt8kfOxH5jstitONizkeYZuYDcChh1PU2vUcg9bY1XmH77yiiJClz4+ -/8KNe78CgYEArTT+XVctYq5jaFCtGqq3DD/DrgJeWS6V5Op0QgVrVKFeCH2mImOg -6+95qwqyl3xCTJNvLwcNB+yricsWfUicEPKfDJX1w8m5/fANMRZYXr2nmAZvS9Kw -pkG0a65+K/m4wnZIszEuNZ2ybjrHEwYdWygRkJUmHp5rzmjdKjCBkwU= ------END RSA PRIVATE KEY----- -""" + -----BEGIN RSA PRIVATE KEY----- + MIIEpQIBAAKCAQEAoQIWz/MQ+mRShQxxxs+zlCLHRz+R1zUPKZhg3eggbXartfyI + OSPEDaVANCjE1QLg0dtGCpkbMAVQLkC7os5ZuW6A6qtSAU6WUBOvnDBPVumqmDUq + AeXGEQyDZqReRm3D4Ov4qOTlIk34pRhoCymaNTiw7GfyzzWOcPxcRGGTz6fv1gmS + wDnURBeL9QUAb2/sdAAsY/SZzziNF+womF8y3mn+IvlKL3EhtSxUfdZpPdFmxPza + oVIlllFQcKnxH4/0PZeyPK0Npq4kCqATXcYXmaa3Ms9tPcsQUggtAR/QepyrKmB1 + SRAouHqKi+bGTlCpFSFbDgW422gfqXEEboh39QIDAQABAoIBAQCRUR9hxFHYjF9m + MhsmgyPjWZhel+N7RypOMneLEQzjfy3vbONOHxe98R4HdZxhXN2oyq1mt1UwfDsn + 48j2YiPdFv1H0CSNhW5pC7t9zqRtHyyXf7RQTh/8Fz0pkMR98GfQQ2oElcKwuYrn + ByYwnPXPf0E/vXoKxp2vIDXuidssmUl37mvbyppGaVl+Is6GmAiZkNOKN8ZEXPvz + 4BivJ3yhs/RiM5RUF93qj8j/3P6R8rXLemAE9jrKjGG7Vv966p1Fh9+wNnnnbT8t + zLDUVwD7Q/JERr+3Wdecp+pZIfWTvJJhE8R3IM4WrLQNeUEKo7YovfYA7rah3gP/ + ixM2BM5pAoGBAM5+c7Sxl7hzII2yPxN2fIslyKw3E8HP1nnqUPUegFsU3TZRQUnZ + gm5JgQRPqFYy6fwouL07KdSb/zIes3ra/qkhaOewHsAvvvxKKM6FGqYrkb5BKv0s + gF/m4qg6GLSW3BVb/QfnwHdWE7z7KPGuomzg+pqshxTyKYkGN2l8IIu7AoGBAMeb + 81636nRy62CYQhNCp13wqmmUJ8/VnNj2jdwdXQ5vlgQdrwFm2p52cEFn/AhL5WIn + GShRLKL/keK71tsD0hCsTuZISR1xFiFk0TFmjxSX+z2D9VGvSECtNfySRuroKorS + xIXsrx6dvk/Ef54yDus1O5vvdT3l6vSDbVJESFgPAoGBAIAFJ8kT/YNOZRVUOATi + Ba7jGvmiH+6d41OscMq3QU62rbr6P2cAofusOH+qvyvJ3wUFXht7raBxopK5M/7r + /MxwuTBDIZ13PIn/lDMNlIsHIhF5J6TUzTYn18gCVMTJbuMTJ9mZ1dpmlFAqyqSj + 53FnPhdc9VaIGDYqk3ojia33AoGAd52bzNH3vMq1BJCZYANcWm4DIPu4k9JViKrP + Pe2WuzThOBw1qGhjb/xXrspKfQpGLnhxmfhzAEaYvL+FtH9onbc0HMmKjwsakO5i + cfEcouGknCt8kfOxH5jstitONizkeYZuYDcChh1PU2vUcg9bY1XmH77yiiJClz4+ + /8KNe78CgYEArTT+XVctYq5jaFCtGqq3DD/DrgJeWS6V5Op0QgVrVKFeCH2mImOg + 6+95qwqyl3xCTJNvLwcNB+yricsWfUicEPKfDJX1w8m5/fANMRZYXr2nmAZvS9Kw + pkG0a65+K/m4wnZIszEuNZ2ybjrHEwYdWygRkJUmHp5rzmjdKjCBkwU= + -----END RSA PRIVATE KEY----- + """ let rsaPublicKey = """ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoQIWz/MQ+mRShQxxxs+z -lCLHRz+R1zUPKZhg3eggbXartfyIOSPEDaVANCjE1QLg0dtGCpkbMAVQLkC7os5Z -uW6A6qtSAU6WUBOvnDBPVumqmDUqAeXGEQyDZqReRm3D4Ov4qOTlIk34pRhoCyma -NTiw7GfyzzWOcPxcRGGTz6fv1gmSwDnURBeL9QUAb2/sdAAsY/SZzziNF+womF8y -3mn+IvlKL3EhtSxUfdZpPdFmxPzaoVIlllFQcKnxH4/0PZeyPK0Npq4kCqATXcYX -maa3Ms9tPcsQUggtAR/QepyrKmB1SRAouHqKi+bGTlCpFSFbDgW422gfqXEEboh3 -9QIDAQAB ------END PUBLIC KEY----- -""" + -----BEGIN PUBLIC KEY----- + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoQIWz/MQ+mRShQxxxs+z + lCLHRz+R1zUPKZhg3eggbXartfyIOSPEDaVANCjE1QLg0dtGCpkbMAVQLkC7os5Z + uW6A6qtSAU6WUBOvnDBPVumqmDUqAeXGEQyDZqReRm3D4Ov4qOTlIk34pRhoCyma + NTiw7GfyzzWOcPxcRGGTz6fv1gmSwDnURBeL9QUAb2/sdAAsY/SZzziNF+womF8y + 3mn+IvlKL3EhtSxUfdZpPdFmxPzaoVIlllFQcKnxH4/0PZeyPK0Npq4kCqATXcYX + maa3Ms9tPcsQUggtAR/QepyrKmB1SRAouHqKi+bGTlCpFSFbDgW422gfqXEEboh3 + 9QIDAQAB + -----END PUBLIC KEY----- + """ let certECPrivateKey = """ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIGfOkQcQq6oTC06KkGMVBAr2MiYFRaLo4/wKdNBpIjhnoAoGCCqGSM49 -AwEHoUQDQgAE6SjFVQRtU/+ywvxslaVsl+iZf65YgkQShuxsbAbNJBTVkEkMGyNL -8nbaj6B4Jskjo1loNPLirNE7mKeTLYbrcw== ------END EC PRIVATE KEY----- -""" + -----BEGIN EC PRIVATE KEY----- + MHcCAQEEIGfOkQcQq6oTC06KkGMVBAr2MiYFRaLo4/wKdNBpIjhnoAoGCCqGSM49 + AwEHoUQDQgAE6SjFVQRtU/+ywvxslaVsl+iZf65YgkQShuxsbAbNJBTVkEkMGyNL + 8nbaj6B4Jskjo1loNPLirNE7mKeTLYbrcw== + -----END EC PRIVATE KEY----- + """ let certRSAPrivateKey = """ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEA13XgJ9lIhR2LefNxQdo3tVrbXEZ3o4T8+MgteVJVohbPMypf -yGgGlJJ/r7+hhL/klsPDyR4SAtgLZUGFVt3WzGMolGyV11VUTTFHMWZ10tcgrUmR -5wg2n5E59FsJf3y3WTs5CpD2tM8igWyAUOyS/MWvhgnMtvBG8I4Mg9xyyWi/GW3g -PLXfnyULW/v2Zg+yG9j+/Bbpx+AP8TCvWoiPyiLEZ/DKZK2kC+8mkwOtHYDMkBO5 -2nIrxopB42VUWYBfAzHm0M2XlEuc26PVojqno2ht5WU486uJXzWILvW3zFdlNDF/ -SLeqQy1mNLRt5/An6la7e3sjOcuI1W2Qe7dkrwIDAQABAoIBAES+eUx9iSPfr1az -k5k9NLUKTh785MMpdUUzKT8iQ+w5dtaOWI0qk57ntxGuBKzERPzNbTRIAdsib1BZ -PV/f297ObG4ezxgrQ4B1jo92b3Vb6jMf3AtolXUH8wPB4B/q/Nzdhm+WnQBHbmz4 -31/ye1tm/3+2tLhRpXCvAdM4jO8xhJlH+Pxg20fliAuiJ+ggSL56CyBR4kg80KtA -omeGB1DOVFd23aDO/79Mii/2tf6EpmVFB/4zBkPHOH3zucwt8XUttwBeOcGdIbP+ -CiU9VdZmG0XOJfC3apAXf9YwU3WVbmbvUWSwt6iHGZD4AuKY2R0ECTZnYS8ThDhd -ZwPXzCECgYEA6xe9MpBCIVRK51Hb083mDg16UjRvPJA4T8w9xFg4UtAwe/u3CC67 -4fAOSe0P3NtsXhcQFby7PEJwoeo2Hn6hUifxVMsKWmHb+FCg+CG/oBSwRKCa5BwG -WpJ0jEt6KHZf0u+b/N1aOjVi/9tMrsHXFV3s2Gm9LQqA8u8izshDqakCgYEA6p8t -KVK2mA+JjvSGyR6WfpVZ1OIi6CEEUhRU3aNHRB2zPf6J3PQLjz+Ad50BCVHXQSy/ -aG3LpR44eUu5Q9AmTwDr8eiC8AT6uyE19zJHbK//E40Bn6khQvtymwByjav/5ZB+ -ZAhE7E31eCZO8bqufSlnMNTD0Z8oqB5YR8uDApcCgYAkPcGd5N089Bij9luUGD6p -1ewQdiLbzEPSEWNIPG1aXtvKkTBTI5k1KGObg98ZJf5btuR05WZb0MY6P7feFZla -5+ttLevHqSRW8F8QQWugCvBtc/DMz4EvPzqWUiBf0nfNNcDvR1RcetRrKux0WE+G -7LbRWeOe6OqeCL1t8TN1GQKBgHPaH6m8/w689VbSpc+fu/5Lby0wcL4gt4p0IafD -nUgkRkLBcn/ZPfABEkV+EGnysJCtMOK2/IzPDGHQo2251YDDWr576lPskYZfks86 -U4x2p0SXJwsYr6Tslp21LduI5/YKUG7Cqo3ovOIUQH0ailihXiP9m6fhqGjDeyIQ -euOHAoGAfDpntw1HRuk812au430Stl5eaTsH+w1msLLKZOukr6qWc2xFeC3fYPWQ -BBkyzM3p6Se9FsfHY6LMxrEkz9fSdeVOeHenyUCTMqhqrc6o9f79zIlocsMzVGsK -XKcULjpf67Igyx12eh3rqAEKwm6PGhbv9pK5/NpuzsP1atArMRg= ------END RSA PRIVATE KEY----- -""" + -----BEGIN RSA PRIVATE KEY----- + MIIEogIBAAKCAQEA13XgJ9lIhR2LefNxQdo3tVrbXEZ3o4T8+MgteVJVohbPMypf + yGgGlJJ/r7+hhL/klsPDyR4SAtgLZUGFVt3WzGMolGyV11VUTTFHMWZ10tcgrUmR + 5wg2n5E59FsJf3y3WTs5CpD2tM8igWyAUOyS/MWvhgnMtvBG8I4Mg9xyyWi/GW3g + PLXfnyULW/v2Zg+yG9j+/Bbpx+AP8TCvWoiPyiLEZ/DKZK2kC+8mkwOtHYDMkBO5 + 2nIrxopB42VUWYBfAzHm0M2XlEuc26PVojqno2ht5WU486uJXzWILvW3zFdlNDF/ + SLeqQy1mNLRt5/An6la7e3sjOcuI1W2Qe7dkrwIDAQABAoIBAES+eUx9iSPfr1az + k5k9NLUKTh785MMpdUUzKT8iQ+w5dtaOWI0qk57ntxGuBKzERPzNbTRIAdsib1BZ + PV/f297ObG4ezxgrQ4B1jo92b3Vb6jMf3AtolXUH8wPB4B/q/Nzdhm+WnQBHbmz4 + 31/ye1tm/3+2tLhRpXCvAdM4jO8xhJlH+Pxg20fliAuiJ+ggSL56CyBR4kg80KtA + omeGB1DOVFd23aDO/79Mii/2tf6EpmVFB/4zBkPHOH3zucwt8XUttwBeOcGdIbP+ + CiU9VdZmG0XOJfC3apAXf9YwU3WVbmbvUWSwt6iHGZD4AuKY2R0ECTZnYS8ThDhd + ZwPXzCECgYEA6xe9MpBCIVRK51Hb083mDg16UjRvPJA4T8w9xFg4UtAwe/u3CC67 + 4fAOSe0P3NtsXhcQFby7PEJwoeo2Hn6hUifxVMsKWmHb+FCg+CG/oBSwRKCa5BwG + WpJ0jEt6KHZf0u+b/N1aOjVi/9tMrsHXFV3s2Gm9LQqA8u8izshDqakCgYEA6p8t + KVK2mA+JjvSGyR6WfpVZ1OIi6CEEUhRU3aNHRB2zPf6J3PQLjz+Ad50BCVHXQSy/ + aG3LpR44eUu5Q9AmTwDr8eiC8AT6uyE19zJHbK//E40Bn6khQvtymwByjav/5ZB+ + ZAhE7E31eCZO8bqufSlnMNTD0Z8oqB5YR8uDApcCgYAkPcGd5N089Bij9luUGD6p + 1ewQdiLbzEPSEWNIPG1aXtvKkTBTI5k1KGObg98ZJf5btuR05WZb0MY6P7feFZla + 5+ttLevHqSRW8F8QQWugCvBtc/DMz4EvPzqWUiBf0nfNNcDvR1RcetRrKux0WE+G + 7LbRWeOe6OqeCL1t8TN1GQKBgHPaH6m8/w689VbSpc+fu/5Lby0wcL4gt4p0IafD + nUgkRkLBcn/ZPfABEkV+EGnysJCtMOK2/IzPDGHQo2251YDDWr576lPskYZfks86 + U4x2p0SXJwsYr6Tslp21LduI5/YKUG7Cqo3ovOIUQH0ailihXiP9m6fhqGjDeyIQ + euOHAoGAfDpntw1HRuk812au430Stl5eaTsH+w1msLLKZOukr6qWc2xFeC3fYPWQ + BBkyzM3p6Se9FsfHY6LMxrEkz9fSdeVOeHenyUCTMqhqrc6o9f79zIlocsMzVGsK + XKcULjpf67Igyx12eh3rqAEKwm6PGhbv9pK5/NpuzsP1atArMRg= + -----END RSA PRIVATE KEY----- + """ diff --git a/Tests/PackageCollectionsTests/GitHubPackageMetadataProviderTests.swift b/Tests/PackageCollectionsTests/GitHubPackageMetadataProviderTests.swift index d29033ce597..f573dbec99b 100644 --- a/Tests/PackageCollectionsTests/GitHubPackageMetadataProviderTests.swift +++ b/Tests/PackageCollectionsTests/GitHubPackageMetadataProviderTests.swift @@ -55,39 +55,75 @@ class GitHubPackageMetadataProviderTests: XCTestCase { case (.get, apiURL): let path = fixturePath.appending(components: "GitHub", "metadata.json") let data: Data = try! localFileSystem.readFileContents(path) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) case (.get, releasesURL): let path = fixturePath.appending(components: "GitHub", "releases.json") let data: Data = try! localFileSystem.readFileContents(path) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) case (.get, apiURL.appendingPathComponent("contributors")): let path = fixturePath.appending(components: "GitHub", "contributors.json") let data: Data = try! localFileSystem.readFileContents(path) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) case (.get, apiURL.appendingPathComponent("readme")): let path = fixturePath.appending(components: "GitHub", "readme.json") let data: Data = try! localFileSystem.readFileContents(path) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) case (.get, apiURL.appendingPathComponent("license")): let path = fixturePath.appending(components: "GitHub", "license.json") let data: Data = try! localFileSystem.readFileContents(path) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) case (.get, apiURL.appendingPathComponent("languages")): let path = fixturePath.appending(components: "GitHub", "languages.json") let data: Data = try! localFileSystem.readFileContents(path) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method and url should match") } @@ -113,9 +149,16 @@ class GitHubPackageMetadataProviderTests: XCTestCase { XCTAssertEqual(metadata.versions[1].title, "1.0.0") XCTAssertEqual(metadata.versions[1].summary, "Description of the release") XCTAssertEqual(metadata.versions[1].author?.username, "octocat") - XCTAssertEqual(metadata.authors, [PackageCollectionsModel.Package.Author(username: "octocat", - url: "https://api.github.com/users/octocat", - service: .init(name: "GitHub"))]) + XCTAssertEqual( + metadata.authors, + [ + PackageCollectionsModel.Package.Author( + username: "octocat", + url: "https://api.github.com/users/octocat", + service: .init(name: "GitHub") + ) + ] + ) XCTAssertEqual(metadata.readmeURL, "https://raw.githubusercontent.com/octokit/octokit.rb/master/README.md") XCTAssertEqual(metadata.license?.type, PackageCollectionsModel.LicenseType.MIT) XCTAssertEqual(metadata.license?.url, "https://raw.githubusercontent.com/benbalter/gman/master/LICENSE?lab=true") @@ -158,9 +201,15 @@ class GitHubPackageMetadataProviderTests: XCTestCase { let handler: LegacyHTTPClient.Handler = { request, _, completion in switch (request.method, request.url) { case (.get, apiURL): - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: completion(.success(.init(statusCode: 500))) } @@ -258,9 +307,15 @@ class GitHubPackageMetadataProviderTests: XCTestCase { } else if request.url == apiURL { remaining = remaining - 1 headers.add(name: "Content-Length", value: "\(data.count)") - completion(.success(.init(statusCode: 200, - headers: headers, - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: headers, + body: data + ) + ) + ) } else { completion(.success(.init(statusCode: 500))) } @@ -276,7 +331,7 @@ class GitHubPackageMetadataProviderTests: XCTestCase { let provider = GitHubPackageMetadataProvider(configuration: configuration, httpClient: httpClient) defer { XCTAssertNoThrow(try provider.close()) } - for index in 0 ... total * 2 { + for index in 0...total * 2 { if index >= total { await XCTAssertAsyncThrowsError(try await provider.syncGet(identity: .init(url: repoURL), location: repoURL.absoluteString), "should throw error") { error in XCTAssertEqual(error as? GitHubPackageMetadataProviderError, .apiLimitsExceeded(apiURL, total)) @@ -326,7 +381,7 @@ class GitHubPackageMetadataProviderTests: XCTestCase { func testForRealz() async throws { #if ENABLE_GITHUB_NETWORK_TEST #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif let repoURL = SourceControlURL("https://github.com/apple/swift-numerics.git") @@ -336,7 +391,7 @@ class GitHubPackageMetadataProviderTests: XCTestCase { httpClient.configuration.retryStrategy = .none httpClient.configuration.requestHeaders = .init() httpClient.configuration.requestHeaders!.add(name: "Cache-Control", value: "no-cache") - var configuration = GitHubPackageMetadataProvider.Configuration(disableCache: true) // Disable cache so we hit the API + var configuration = GitHubPackageMetadataProvider.Configuration(disableCache: true) // Disable cache so we hit the API if let token = Environment.current["GITHUB_API_TOKEN"] { configuration.authTokens = { [.github("github.com"): token] } } @@ -344,7 +399,7 @@ class GitHubPackageMetadataProviderTests: XCTestCase { let provider = GitHubPackageMetadataProvider(configuration: configuration, httpClient: httpClient) defer { XCTAssertNoThrow(try provider.close()) } - for _ in 0 ... 60 { + for _ in 0...60 { let metadata = try await provider.syncGet(identity: .init(url: repoURL), location: repoURL.absoluteString) XCTAssertNotNil(metadata) XCTAssert(metadata.versions.count > 0) diff --git a/Tests/PackageCollectionsTests/JSONPackageCollectionProviderTests.swift b/Tests/PackageCollectionsTests/JSONPackageCollectionProviderTests.swift index 7b3379d9add..9213d944444 100644 --- a/Tests/PackageCollectionsTests/JSONPackageCollectionProviderTests.swift +++ b/Tests/PackageCollectionsTests/JSONPackageCollectionProviderTests.swift @@ -31,12 +31,24 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]) + ) + ) + ) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method should match") } @@ -79,7 +91,7 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(version.signer?.commonName, "J. Appleseed") XCTAssertNotNil(version.createdAt) XCTAssertFalse(collection.isSigned) - + XCTAssertEqual(collection.packages[1].identity, .init(urlString: "https://www.example.com/repos/RepoTwo.git")) // "1.8.3" is originally "v1.8.3" @@ -127,7 +139,7 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(version.signer?.commonName, "J. Appleseed") XCTAssertNotNil(version.createdAt) XCTAssertFalse(collection.isSigned) - + XCTAssertEqual(collection.packages[1].identity, .init(urlString: "https://www.example.com/repos/RepoTwo.git")) // "1.8.3" is originally "v1.8.3" @@ -142,12 +154,16 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none let provider = JSONPackageCollectionProvider(httpClient: httpClient) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - guard case .invalidSource(let errorMessage) = error as? JSONPackageCollectionProviderError else { - return XCTFail("invalid error \(error)") + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + guard case .invalidSource(let errorMessage) = error as? JSONPackageCollectionProviderError else { + return XCTFail("invalid error \(error)") + } + XCTAssertTrue(errorMessage.contains("Scheme (\"ftp\") not allowed: \(url.absoluteString)")) } - XCTAssertTrue(errorMessage.contains("Scheme (\"ftp\") not allowed: \(url.absoluteString)")) - }) + ) } func testExceedsDownloadSizeLimitHead() async throws { @@ -158,8 +174,14 @@ class JSONPackageCollectionProviderTests: XCTestCase { let handler: LegacyHTTPClient.Handler = { request, _, completion in XCTAssertEqual(request.url, url, "url should match") XCTAssertEqual(request.method, .head, "method should match") - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(maxSize * 2)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(maxSize * 2)")]) + ) + ) + ) } let httpClient = LegacyHTTPClient(handler: handler) @@ -167,9 +189,13 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.retryStrategy = .none let configuration = JSONPackageCollectionProvider.Configuration(maximumSizeInBytes: 10) let provider = JSONPackageCollectionProvider(configuration: configuration, httpClient: httpClient) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - XCTAssertEqual(error as? JSONPackageCollectionProviderError, .responseTooLarge(url, maxSize * 2)) - }) + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + XCTAssertEqual(error as? JSONPackageCollectionProviderError, .responseTooLarge(url, maxSize * 2)) + } + ) } func testExceedsDownloadSizeLimitGet() async throws { @@ -181,11 +207,23 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "0")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "0")]) + ) + ) + ) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(maxSize * 2)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(maxSize * 2)")]) + ) + ) + ) default: XCTFail("method should match") } @@ -196,9 +234,13 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.retryStrategy = .none let configuration = JSONPackageCollectionProvider.Configuration(maximumSizeInBytes: 10) let provider = JSONPackageCollectionProvider(configuration: configuration, httpClient: httpClient) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - XCTAssertEqual(error as? JSONPackageCollectionProviderError, .responseTooLarge(url, maxSize * 2)) - }) + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + XCTAssertEqual(error as? JSONPackageCollectionProviderError, .responseTooLarge(url, maxSize * 2)) + } + ) } func testNoContentLengthOnGet() async throws { @@ -216,9 +258,13 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.retryStrategy = .none let configuration = JSONPackageCollectionProvider.Configuration(maximumSizeInBytes: 10) let provider = JSONPackageCollectionProvider(configuration: configuration, httpClient: httpClient) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - XCTAssertEqual(error as? JSONPackageCollectionProviderError, .invalidResponse(url, "Missing Content-Length header")) - }) + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + XCTAssertEqual(error as? JSONPackageCollectionProviderError, .invalidResponse(url, "Missing Content-Length header")) + } + ) } func testExceedsDownloadSizeLimitProgress() async throws { @@ -230,8 +276,14 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "0")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "0")]) + ) + ) + ) case .get: do { try progress?(Int64(maxSize * 2), 0) @@ -248,15 +300,19 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.retryStrategy = .none let configuration = JSONPackageCollectionProvider.Configuration(maximumSizeInBytes: 10) let provider = JSONPackageCollectionProvider(configuration: configuration, httpClient: httpClient) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - XCTAssertEqual(error as? HTTPClientError, .responseTooLarge(maxSize * 2)) - }) + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + XCTAssertEqual(error as? HTTPClientError, .responseTooLarge(maxSize * 2)) + } + ) } func testUnsuccessfulHead_unavailable() async throws { let url = URL("https://www.test.com/collection.json") let source = PackageCollectionsModel.CollectionSource(type: .json, url: url) - let statusCode = Int.random(in: 500 ... 550) // Don't use 404 because it leads to a different error message + let statusCode = Int.random(in: 500...550) // Don't use 404 because it leads to a different error message let handler: LegacyHTTPClient.Handler = { request, _, completion in XCTAssertEqual(request.url, url, "url should match") @@ -268,15 +324,19 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none let provider = JSONPackageCollectionProvider(httpClient: httpClient) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - XCTAssertEqual(error as? JSONPackageCollectionProviderError, .collectionUnavailable(url, statusCode)) - }) + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + XCTAssertEqual(error as? JSONPackageCollectionProviderError, .collectionUnavailable(url, statusCode)) + } + ) } func testUnsuccessfulGet_unavailable() async throws { let url = URL("https://www.test.com/collection.json") let source = PackageCollectionsModel.CollectionSource(type: .json, url: url) - let statusCode = Int.random(in: 500 ... 550) // Don't use 404 because it leads to a different error message + let statusCode = Int.random(in: 500...550) // Don't use 404 because it leads to a different error message let handler: LegacyHTTPClient.Handler = { request, _, completion in XCTAssertEqual(request.url, url, "url should match") @@ -294,9 +354,13 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none let provider = JSONPackageCollectionProvider(httpClient: httpClient) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - XCTAssertEqual(error as? JSONPackageCollectionProviderError, .collectionUnavailable(url, statusCode)) - }) + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + XCTAssertEqual(error as? JSONPackageCollectionProviderError, .collectionUnavailable(url, statusCode)) + } + ) } func testUnsuccessfulHead_notFound() async throws { @@ -313,9 +377,13 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none let provider = JSONPackageCollectionProvider(httpClient: httpClient) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - XCTAssertEqual(error as? JSONPackageCollectionProviderError, .collectionNotFound(url)) - }) + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + XCTAssertEqual(error as? JSONPackageCollectionProviderError, .collectionNotFound(url)) + } + ) } func testUnsuccessfulGet_notFound() async throws { @@ -338,9 +406,13 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none let provider = JSONPackageCollectionProvider(httpClient: httpClient) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - XCTAssertEqual(error as? JSONPackageCollectionProviderError, .collectionNotFound(url)) - }) + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + XCTAssertEqual(error as? JSONPackageCollectionProviderError, .collectionNotFound(url)) + } + ) } func testBadJSON() async throws { @@ -353,9 +425,15 @@ class JSONPackageCollectionProviderTests: XCTestCase { case .head: completion(.success(.init(statusCode: 200, headers: .init([.init(name: "Content-Length", value: "\(data.count)")])))) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method should match") } @@ -366,9 +444,13 @@ class JSONPackageCollectionProviderTests: XCTestCase { httpClient.configuration.retryStrategy = .none let provider = JSONPackageCollectionProvider(httpClient: httpClient) let source = PackageCollectionsModel.CollectionSource(type: .json, url: url) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - XCTAssertEqual(error as? JSONPackageCollectionProviderError, .invalidJSON(url)) - }) + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + XCTAssertEqual(error as? JSONPackageCollectionProviderError, .invalidJSON(url)) + } + ) } func testSignedGood() async throws { @@ -383,12 +465,24 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]) + ) + ) + ) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method should match") } @@ -438,7 +532,7 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertTrue(signature.isVerified) XCTAssertEqual("Sample Subject", signature.certificate.subject.commonName) XCTAssertEqual("Sample Issuer", signature.certificate.issuer.commonName) - + XCTAssertEqual(collection.packages[1].identity, .init(urlString: "https://www.example.com/repos/RepoTwo.git")) // "1.8.3" is originally "v1.8.3" @@ -456,12 +550,24 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]) + ) + ) + ) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method should match") } @@ -510,7 +616,7 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertFalse(signature.isVerified) XCTAssertEqual("Sample Subject", signature.certificate.subject.commonName) XCTAssertEqual("Sample Issuer", signature.certificate.issuer.commonName) - + XCTAssertEqual(collection.packages[1].identity, .init(urlString: "https://www.example.com/repos/RepoTwo.git")) } } @@ -527,12 +633,24 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]) + ) + ) + ) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method should match") } @@ -546,14 +664,18 @@ class JSONPackageCollectionProviderTests: XCTestCase { let provider = JSONPackageCollectionProvider(httpClient: httpClient, signatureValidator: signatureValidator) let source = PackageCollectionsModel.CollectionSource(type: .json, url: url) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - switch error { - case PackageCollectionError.cannotVerifySignature: - break - default: - XCTFail("unexpected error \(error)") + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + switch error { + case PackageCollectionError.cannotVerifySignature: + break + default: + XCTFail("unexpected error \(error)") + } } - }) + ) } } @@ -569,12 +691,24 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]) + ) + ) + ) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method should match") } @@ -589,14 +723,18 @@ class JSONPackageCollectionProviderTests: XCTestCase { let provider = JSONPackageCollectionProvider(httpClient: httpClient, signatureValidator: signatureValidator) let source = PackageCollectionsModel.CollectionSource(type: .json, url: url) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - switch error { - case PackageCollectionError.invalidSignature: - break - default: - XCTFail("unexpected error \(error)") + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + switch error { + case PackageCollectionError.invalidSignature: + break + default: + XCTFail("unexpected error \(error)") + } } - }) + ) } } @@ -664,12 +802,24 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]) + ) + ) + ) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method should match") } @@ -685,8 +835,11 @@ class JSONPackageCollectionProviderTests: XCTestCase { let sourceCertPolicy = PackageCollectionSourceCertificatePolicy( sourceCertPolicies: ["www.test.com": [.init(certPolicyKey: CertificatePolicyKey.default, base64EncodedRootCerts: nil)]] ) - let provider = JSONPackageCollectionProvider(httpClient: httpClient, signatureValidator: signatureValidator, - sourceCertPolicy: sourceCertPolicy) + let provider = JSONPackageCollectionProvider( + httpClient: httpClient, + signatureValidator: signatureValidator, + sourceCertPolicy: sourceCertPolicy + ) let source = PackageCollectionsModel.CollectionSource(type: .json, url: url) let collection = try await provider.get(source) @@ -723,7 +876,7 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertTrue(signature.isVerified) XCTAssertEqual("Sample Subject", signature.certificate.subject.commonName) XCTAssertEqual("Sample Issuer", signature.certificate.issuer.commonName) - + XCTAssertEqual(collection.packages[1].identity, .init(urlString: "https://www.example.com/repos/RepoTwo.git")) } } @@ -738,12 +891,24 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]) + ) + ) + ) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method should match") } @@ -761,11 +926,14 @@ class JSONPackageCollectionProviderTests: XCTestCase { "www.test.com": [ .init(certPolicyKey: CertificatePolicyKey.default, base64EncodedRootCerts: nil), .init(certPolicyKey: CertificatePolicyKey.default(subjectUserID: "test"), base64EncodedRootCerts: nil), - ], + ] ] ) - let provider = JSONPackageCollectionProvider(httpClient: httpClient, signatureValidator: signatureValidator, - sourceCertPolicy: sourceCertPolicy) + let provider = JSONPackageCollectionProvider( + httpClient: httpClient, + signatureValidator: signatureValidator, + sourceCertPolicy: sourceCertPolicy + ) let source = PackageCollectionsModel.CollectionSource(type: .json, url: url) let collection = try await provider.get(source) @@ -802,7 +970,7 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertTrue(signature.isVerified) XCTAssertEqual("Sample Subject", signature.certificate.subject.commonName) XCTAssertEqual("Sample Issuer", signature.certificate.issuer.commonName) - + XCTAssertEqual(collection.packages[1].identity, .init(urlString: "https://www.example.com/repos/RepoTwo.git")) } } @@ -817,12 +985,24 @@ class JSONPackageCollectionProviderTests: XCTestCase { XCTAssertEqual(request.url, url, "url should match") switch request.method { case .head: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")])))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]) + ) + ) + ) case .get: - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method should match") } @@ -838,18 +1018,25 @@ class JSONPackageCollectionProviderTests: XCTestCase { let sourceCertPolicy = PackageCollectionSourceCertificatePolicy( sourceCertPolicies: ["www.test.com": [.init(certPolicyKey: CertificatePolicyKey.default, base64EncodedRootCerts: nil)]] ) - let provider = JSONPackageCollectionProvider(httpClient: httpClient, signatureValidator: signatureValidator, - sourceCertPolicy: sourceCertPolicy) + let provider = JSONPackageCollectionProvider( + httpClient: httpClient, + signatureValidator: signatureValidator, + sourceCertPolicy: sourceCertPolicy + ) let source = PackageCollectionsModel.CollectionSource(type: .json, url: url) - await XCTAssertAsyncThrowsError(try await provider.get(source), "expected error", { error in - switch error { - case PackageCollectionError.missingSignature: - break - default: - XCTFail("unexpected error \(error)") + await XCTAssertAsyncThrowsError( + try await provider.get(source), + "expected error", + { error in + switch error { + case PackageCollectionError.missingSignature: + break + default: + XCTFail("unexpected error \(error)") + } } - }) + ) } } } @@ -875,7 +1062,7 @@ internal extension JSONPackageCollectionProvider { fileSystem: fileSystem, observabilityScope: ObservabilitySystem.NOOP, sourceCertPolicy: sourceCertPolicy, - customHTTPClient: httpClient , + customHTTPClient: httpClient, customSignatureValidator: signatureValidator ) } diff --git a/Tests/PackageCollectionsTests/PackageCollectionSourceCertificatePolicyTests.swift b/Tests/PackageCollectionsTests/PackageCollectionSourceCertificatePolicyTests.swift index 548cc11a6cd..ee9163eedad 100644 --- a/Tests/PackageCollectionsTests/PackageCollectionSourceCertificatePolicyTests.swift +++ b/Tests/PackageCollectionsTests/PackageCollectionSourceCertificatePolicyTests.swift @@ -29,10 +29,12 @@ final class PackageCollectionSourceCertificatePolicyTests: XCTestCase { base64EncodedRootCerts: ["root-cert-1c"] ), ], - "package-collection-2": [PackageCollectionSourceCertificatePolicy.CertificatePolicyConfig( - certPolicyKey: CertificatePolicyKey.default, - base64EncodedRootCerts: ["root-cert-2"] - )], + "package-collection-2": [ + PackageCollectionSourceCertificatePolicy.CertificatePolicyConfig( + certPolicyKey: CertificatePolicyKey.default, + base64EncodedRootCerts: ["root-cert-2"] + ) + ], ]) let source1 = Model.CollectionSource(type: .json, url: "https://package-collection-1") let unsignedSource = Model.CollectionSource(type: .json, url: "https://package-collection-unsigned") diff --git a/Tests/PackageCollectionsTests/PackageCollectionValidationTests.swift b/Tests/PackageCollectionsTests/PackageCollectionValidationTests.swift index 51b929e0fcf..0f691069a6e 100644 --- a/Tests/PackageCollectionsTests/PackageCollectionValidationTests.swift +++ b/Tests/PackageCollectionsTests/PackageCollectionValidationTests.swift @@ -37,7 +37,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -56,7 +56,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -68,7 +68,7 @@ class PackageCollectionValidationTests: XCTestCase { ], readmeURL: nil, license: nil - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", @@ -124,7 +124,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -132,7 +132,7 @@ class PackageCollectionValidationTests: XCTestCase { author: nil, signer: nil, createdAt: nil - ), + ) ], readmeURL: nil, license: nil @@ -152,7 +152,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Baz", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -160,7 +160,7 @@ class PackageCollectionValidationTests: XCTestCase { author: nil, signer: nil, createdAt: nil - ), + ) ], readmeURL: nil, license: nil @@ -196,7 +196,7 @@ class PackageCollectionValidationTests: XCTestCase { versions: [], readmeURL: nil, license: nil - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", @@ -236,7 +236,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [], products: [], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -255,7 +255,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -267,7 +267,7 @@ class PackageCollectionValidationTests: XCTestCase { ], readmeURL: nil, license: nil - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", @@ -317,7 +317,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -325,11 +325,11 @@ class PackageCollectionValidationTests: XCTestCase { author: nil, signer: nil, createdAt: nil - ), + ) ], readmeURL: nil, license: nil - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", @@ -369,7 +369,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -388,7 +388,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -416,7 +416,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Baz", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -435,7 +435,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Baz", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -492,11 +492,11 @@ class PackageCollectionValidationTests: XCTestCase { author: nil, signer: nil, createdAt: nil - ), + ) ], readmeURL: nil, license: nil - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", @@ -536,7 +536,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: [])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.2", verifiedCompatibility: nil, @@ -544,11 +544,11 @@ class PackageCollectionValidationTests: XCTestCase { author: nil, signer: nil, createdAt: nil - ), + ) ], readmeURL: nil, license: nil - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", @@ -588,7 +588,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.1", verifiedCompatibility: nil, @@ -596,11 +596,11 @@ class PackageCollectionValidationTests: XCTestCase { author: nil, signer: nil, createdAt: nil - ), + ) ], readmeURL: nil, license: nil - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", @@ -640,7 +640,7 @@ class PackageCollectionValidationTests: XCTestCase { targets: [.init(name: "Foo", moduleName: "Foo")], products: [.init(name: "Bar", type: .library(.automatic), targets: ["Foo"])], minimumPlatformVersions: nil - ), + ) ], defaultToolsVersion: "5.1", verifiedCompatibility: nil, @@ -648,11 +648,11 @@ class PackageCollectionValidationTests: XCTestCase { author: nil, signer: nil, createdAt: nil - ), + ) ], readmeURL: nil, license: nil - ), + ) ] let collection = Model.Collection( name: "Test Package Collection", diff --git a/Tests/PackageCollectionsTests/PackageCollectionsModelTests.swift b/Tests/PackageCollectionsTests/PackageCollectionsModelTests.swift index 76ef89629ba..0b348a82020 100644 --- a/Tests/PackageCollectionsTests/PackageCollectionsModelTests.swift +++ b/Tests/PackageCollectionsTests/PackageCollectionsModelTests.swift @@ -21,9 +21,15 @@ final class PackageCollectionsModelTests: XCTestCase { let targets = [PackageCollectionsModel.Target(name: "Foo", moduleName: "Foo")] let products = [PackageCollectionsModel.Product(name: "Foo", type: .library(.automatic), targets: targets)] let toolsVersion = ToolsVersion(string: "5.2")! - let manifests = [toolsVersion: PackageCollectionsModel.Package.Version.Manifest( - toolsVersion: toolsVersion, packageName: "FooBar", targets: targets, products: products, minimumPlatformVersions: nil - )] + let manifests = [ + toolsVersion: PackageCollectionsModel.Package.Version.Manifest( + toolsVersion: toolsVersion, + packageName: "FooBar", + targets: targets, + products: products, + minimumPlatformVersions: nil + ) + ] let versions: [PackageCollectionsModel.Package.Version] = [ .init(version: .init(stringLiteral: "1.2.0"), title: nil, summary: nil, manifests: manifests, defaultToolsVersion: toolsVersion, verifiedCompatibility: nil, license: nil, author: nil, signer: nil, createdAt: nil), .init(version: .init(stringLiteral: "2.0.1"), title: nil, summary: nil, manifests: manifests, defaultToolsVersion: toolsVersion, verifiedCompatibility: nil, license: nil, author: nil, signer: nil, createdAt: nil), @@ -40,9 +46,15 @@ final class PackageCollectionsModelTests: XCTestCase { let targets = [PackageCollectionsModel.Target(name: "Foo", moduleName: "Foo")] let products = [PackageCollectionsModel.Product(name: "Foo", type: .library(.automatic), targets: targets)] let toolsVersion = ToolsVersion(string: "5.2")! - let manifests = [toolsVersion: PackageCollectionsModel.Package.Version.Manifest( - toolsVersion: toolsVersion, packageName: "FooBar", targets: targets, products: products, minimumPlatformVersions: nil - )] + let manifests = [ + toolsVersion: PackageCollectionsModel.Package.Version.Manifest( + toolsVersion: toolsVersion, + packageName: "FooBar", + targets: targets, + products: products, + minimumPlatformVersions: nil + ) + ] let versions: [PackageCollectionsModel.Package.Version] = [ .init(version: .init(stringLiteral: "2.1.0-beta.3"), title: nil, summary: nil, manifests: manifests, defaultToolsVersion: toolsVersion, verifiedCompatibility: nil, license: nil, author: nil, signer: nil, createdAt: nil), .init(version: .init(stringLiteral: "3.0.0-beta.1"), title: nil, summary: nil, manifests: manifests, defaultToolsVersion: toolsVersion, verifiedCompatibility: nil, license: nil, author: nil, signer: nil, createdAt: nil), @@ -56,9 +68,15 @@ final class PackageCollectionsModelTests: XCTestCase { let targets = [PackageCollectionsModel.Target(name: "Foo", moduleName: "Foo")] let products = [PackageCollectionsModel.Product(name: "Foo", type: .library(.automatic), targets: targets)] let toolsVersion = ToolsVersion(string: "5.2")! - let manifests = [toolsVersion: PackageCollectionsModel.Package.Version.Manifest( - toolsVersion: toolsVersion, packageName: "FooBar", targets: targets, products: products, minimumPlatformVersions: nil - )] + let manifests = [ + toolsVersion: PackageCollectionsModel.Package.Version.Manifest( + toolsVersion: toolsVersion, + packageName: "FooBar", + targets: targets, + products: products, + minimumPlatformVersions: nil + ) + ] let versions: [PackageCollectionsModel.Package.Version] = [ .init(version: .init(stringLiteral: "1.2.0"), title: nil, summary: nil, manifests: manifests, defaultToolsVersion: toolsVersion, verifiedCompatibility: nil, license: nil, author: nil, signer: nil, createdAt: nil), .init(version: .init(stringLiteral: "2.0.1"), title: nil, summary: nil, manifests: manifests, defaultToolsVersion: toolsVersion, verifiedCompatibility: nil, license: nil, author: nil, signer: nil, createdAt: nil), diff --git a/Tests/PackageCollectionsTests/PackageCollectionsSourcesStorageTest.swift b/Tests/PackageCollectionsTests/PackageCollectionsSourcesStorageTest.swift index 73ad66fcb13..99fbe244aa0 100644 --- a/Tests/PackageCollectionsTests/PackageCollectionsSourcesStorageTest.swift +++ b/Tests/PackageCollectionsTests/PackageCollectionsSourcesStorageTest.swift @@ -167,8 +167,12 @@ final class PackageCollectionsSourcesStorageTest: XCTestCase { XCTAssertNotEqual(buffer.count, 0, "expected file to be written") print(buffer) - await XCTAssertAsyncThrowsError(try await storage.list(), "expected an error", { error in - XCTAssert(error is DecodingError, "expected error to match") - }) + await XCTAssertAsyncThrowsError( + try await storage.list(), + "expected an error", + { error in + XCTAssert(error is DecodingError, "expected error to match") + } + ) } } diff --git a/Tests/PackageCollectionsTests/PackageCollectionsStorageTests.swift b/Tests/PackageCollectionsTests/PackageCollectionsStorageTests.swift index 25742fd1b70..6b8d7e759bd 100644 --- a/Tests/PackageCollectionsTests/PackageCollectionsStorageTests.swift +++ b/Tests/PackageCollectionsTests/PackageCollectionsStorageTests.swift @@ -25,9 +25,13 @@ class PackageCollectionsStorageTests: XCTestCase { let mockSources = makeMockSources() for source in mockSources { - await XCTAssertAsyncThrowsError(try await storage.get(identifier: .init(from: source)), "expected error", { error in - XCTAssert(error is NotFoundError, "Expected NotFoundError") - }) + await XCTAssertAsyncThrowsError( + try await storage.get(identifier: .init(from: source)), + "expected error", + { error in + XCTAssert(error is NotFoundError, "Expected NotFoundError") + } + ) } let mockCollections = makeMockCollections(count: 50) @@ -46,7 +50,7 @@ class PackageCollectionsStorageTests: XCTestCase { } do { - let count = Int.random(in: 1 ..< mockCollections.count) + let count = Int.random(in: 1.. PackageCollectionsModel.Package in makeMockPackage(id: "package-\(packageIndex)") } @@ -357,10 +377,10 @@ class PackageIndexAndCollectionsTests: XCTestCase { let result = try await indexAndCollections.listPackagesInIndex(offset: 1, limit: 5) XCTAssertFalse(result.items.isEmpty) } - + func testGetPackageMetadata() async throws { try PackageCollectionsTests_skipIfUnsupportedPlatform() - + let storage = makeMockStorage() defer { XCTAssertNoThrow(try storage.close()) } let mockCollections = makeMockCollections(count: 3) @@ -372,7 +392,7 @@ class PackageIndexAndCollectionsTests: XCTestCase { let packageIndex = MockPackageIndex(packages: mockCollections.last!.packages) let indexAndCollections = PackageIndexAndCollections(index: packageIndex, collections: packageCollections, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try indexAndCollections.close()) } - + do { let list = try await indexAndCollections.listCollections() XCTAssertEqual(list.count, 0, "list should be empty") @@ -385,21 +405,21 @@ class PackageIndexAndCollectionsTests: XCTestCase { let list = try await indexAndCollections.listCollections() XCTAssertEqual(list.count, mockCollections.count, "list count should match") } - + let metadata = try await indexAndCollections.getPackageMetadata(identity: mockPackage.identity, location: mockPackage.location) - + let expectedCollections = Set(mockCollections.filter { $0.packages.map { $0.identity }.contains(mockPackage.identity) }.map { $0.identifier }) XCTAssertEqual(Set(metadata.collections), expectedCollections, "collections should match") - + // Metadata comes from package index - package returned as-is, no merging XCTAssertEqual(metadata.package, mockPackage) XCTAssertNotNil(metadata.provider) XCTAssertEqual(metadata.provider?.name, "package index") } - + func testGetPackageMetadata_brokenIndex() async throws { try PackageCollectionsTests_skipIfUnsupportedPlatform() - + let storage = makeMockStorage() defer { XCTAssertNoThrow(try storage.close()) } let mockCollections = makeMockCollections(count: 3) @@ -411,7 +431,7 @@ class PackageIndexAndCollectionsTests: XCTestCase { let packageIndex = BrokenPackageIndex() let indexAndCollections = PackageIndexAndCollections(index: packageIndex, collections: packageCollections, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try indexAndCollections.close()) } - + do { let list = try await indexAndCollections.listCollections() XCTAssertEqual(list.count, 0, "list should be empty") @@ -424,22 +444,22 @@ class PackageIndexAndCollectionsTests: XCTestCase { let list = try await indexAndCollections.listCollections() XCTAssertEqual(list.count, mockCollections.count, "list count should match") } - + let metadata = try await indexAndCollections.getPackageMetadata(identity: mockPackage.identity, location: mockPackage.location) let expectedCollections = Set(mockCollections.filter { $0.packages.map { $0.identity }.contains(mockPackage.identity) }.map { $0.identifier }) XCTAssertEqual(Set(metadata.collections), expectedCollections, "collections should match") - + // Metadata comes from collections - merged with basic metadata let expectedMetadata = PackageCollections.mergedPackageMetadata(package: mockPackage, basicMetadata: mockMetadata) XCTAssertEqual(metadata.package, expectedMetadata, "package should match") XCTAssertNil(metadata.provider) } - + func testGetPackageMetadata_indexAndCollectionError() async throws { try PackageCollectionsTests_skipIfUnsupportedPlatform() - + let storage = makeMockStorage() defer { XCTAssertNoThrow(try storage.close()) } let packageCollections = makePackageCollections(mockCollections: [], storage: storage) @@ -447,7 +467,7 @@ class PackageIndexAndCollectionsTests: XCTestCase { let packageIndex = BrokenPackageIndex() let indexAndCollections = PackageIndexAndCollections(index: packageIndex, collections: packageCollections, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try indexAndCollections.close()) } - + let mockPackage = makeMockPackage(id: "test-package") // Package not found in collections; index is broken await XCTAssertAsyncThrowsError(try await indexAndCollections.getPackageMetadata(identity: mockPackage.identity, location: mockPackage.location)) { error in @@ -457,10 +477,10 @@ class PackageIndexAndCollectionsTests: XCTestCase { } } } - + func testFindPackages() async throws { try PackageCollectionsTests_skipIfUnsupportedPlatform() - + let storage = makeMockStorage() defer { XCTAssertNoThrow(try storage.close()) } @@ -470,8 +490,10 @@ class PackageIndexAndCollectionsTests: XCTestCase { PackageCollectionsModel.Target(name: $0, moduleName: $0) } - let mockProducts = [PackageCollectionsModel.Product(name: UUID().uuidString, type: .executable, targets: [mockTargets.first!]), - PackageCollectionsModel.Product(name: UUID().uuidString, type: .executable, targets: mockTargets)] + let mockProducts = [ + PackageCollectionsModel.Product(name: UUID().uuidString, type: .executable, targets: [mockTargets.first!]), + PackageCollectionsModel.Product(name: UUID().uuidString, type: .executable, targets: mockTargets), + ] let toolsVersion = ToolsVersion(string: "5.2")! let mockManifest = PackageCollectionsModel.Package.Version.Manifest( toolsVersion: toolsVersion, @@ -481,46 +503,54 @@ class PackageIndexAndCollectionsTests: XCTestCase { minimumPlatformVersions: nil ) - let mockVersion = PackageCollectionsModel.Package.Version(version: TSCUtility.Version(1, 0, 0), - title: nil, - summary: nil, - manifests: [toolsVersion: mockManifest], - defaultToolsVersion: toolsVersion, - verifiedCompatibility: nil, - license: nil, - author: nil, - signer: nil, - createdAt: nil) + let mockVersion = PackageCollectionsModel.Package.Version( + version: TSCUtility.Version(1, 0, 0), + title: nil, + summary: nil, + manifests: [toolsVersion: mockManifest], + defaultToolsVersion: toolsVersion, + verifiedCompatibility: nil, + license: nil, + author: nil, + signer: nil, + createdAt: nil + ) let url = "https://packages.mock/\(UUID().uuidString)" - let mockPackage = PackageCollectionsModel.Package(identity: .init(urlString: url), - location: url, - summary: UUID().uuidString, - keywords: [UUID().uuidString, UUID().uuidString], - versions: [mockVersion], - watchersCount: nil, - readmeURL: nil, - license: nil, - authors: nil, - languages: nil) - - let mockCollection = PackageCollectionsModel.Collection(source: .init(type: .json, url: "https://feed.mock/\(UUID().uuidString)"), - name: UUID().uuidString, - overview: UUID().uuidString, - keywords: [UUID().uuidString, UUID().uuidString], - packages: [mockPackage], - createdAt: Date(), - createdBy: nil, - signature: nil) - - let mockCollection2 = PackageCollectionsModel.Collection(source: .init(type: .json, url: "https://feed.mock/\(UUID().uuidString)"), - name: UUID().uuidString, - overview: UUID().uuidString, - keywords: [UUID().uuidString, UUID().uuidString], - packages: [mockPackage], - createdAt: Date(), - createdBy: nil, - signature: nil) + let mockPackage = PackageCollectionsModel.Package( + identity: .init(urlString: url), + location: url, + summary: UUID().uuidString, + keywords: [UUID().uuidString, UUID().uuidString], + versions: [mockVersion], + watchersCount: nil, + readmeURL: nil, + license: nil, + authors: nil, + languages: nil + ) + + let mockCollection = PackageCollectionsModel.Collection( + source: .init(type: .json, url: "https://feed.mock/\(UUID().uuidString)"), + name: UUID().uuidString, + overview: UUID().uuidString, + keywords: [UUID().uuidString, UUID().uuidString], + packages: [mockPackage], + createdAt: Date(), + createdBy: nil, + signature: nil + ) + + let mockCollection2 = PackageCollectionsModel.Collection( + source: .init(type: .json, url: "https://feed.mock/\(UUID().uuidString)"), + name: UUID().uuidString, + overview: UUID().uuidString, + keywords: [UUID().uuidString, UUID().uuidString], + packages: [mockPackage], + createdAt: Date(), + createdBy: nil, + signature: nil + ) let expectedCollections = [mockCollection, mockCollection2] let expectedCollectionsIdentifiers = expectedCollections.map { $0.identifier }.sorted() @@ -531,11 +561,11 @@ class PackageIndexAndCollectionsTests: XCTestCase { let packageIndex = MockPackageIndex(packages: [mockPackage]) let indexAndCollections = PackageIndexAndCollections(index: packageIndex, collections: packageCollections, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try indexAndCollections.close()) } - + for collection in mockCollections { _ = try await indexAndCollections.addCollection(collection.source, trustConfirmationProvider: { _, cb in cb(true) }) } - + // both index and collections do { let searchResult = try await indexAndCollections.findPackages(mockPackage.identity.description, in: .both(collections: nil)) @@ -543,7 +573,7 @@ class PackageIndexAndCollectionsTests: XCTestCase { XCTAssertEqual(searchResult.items.first?.collections.sorted(), expectedCollectionsIdentifiers, "collections should match") XCTAssertEqual(searchResult.items.first?.indexes, [packageIndex.url], "indexes should match") } - + // index only do { let searchResult = try await indexAndCollections.findPackages(mockPackage.identity.description, in: .index) @@ -551,7 +581,7 @@ class PackageIndexAndCollectionsTests: XCTestCase { XCTAssertTrue(searchResult.items.first?.collections.isEmpty ?? true, "collections should match") XCTAssertEqual(searchResult.items.first?.indexes, [packageIndex.url], "indexes should match") } - + // collections only do { let searchResult = try await indexAndCollections.findPackages(mockPackage.identity.description, in: .collections(nil)) @@ -560,10 +590,10 @@ class PackageIndexAndCollectionsTests: XCTestCase { XCTAssertTrue(searchResult.items.first?.indexes.isEmpty ?? true, "indexes should match") } } - + func testFindPackages_brokenIndex() async throws { try PackageCollectionsTests_skipIfUnsupportedPlatform() - + let storage = makeMockStorage() defer { XCTAssertNoThrow(try storage.close()) } @@ -573,8 +603,10 @@ class PackageIndexAndCollectionsTests: XCTestCase { PackageCollectionsModel.Target(name: $0, moduleName: $0) } - let mockProducts = [PackageCollectionsModel.Product(name: UUID().uuidString, type: .executable, targets: [mockTargets.first!]), - PackageCollectionsModel.Product(name: UUID().uuidString, type: .executable, targets: mockTargets)] + let mockProducts = [ + PackageCollectionsModel.Product(name: UUID().uuidString, type: .executable, targets: [mockTargets.first!]), + PackageCollectionsModel.Product(name: UUID().uuidString, type: .executable, targets: mockTargets), + ] let toolsVersion = ToolsVersion(string: "5.2")! let mockManifest = PackageCollectionsModel.Package.Version.Manifest( toolsVersion: toolsVersion, @@ -584,46 +616,54 @@ class PackageIndexAndCollectionsTests: XCTestCase { minimumPlatformVersions: nil ) - let mockVersion = PackageCollectionsModel.Package.Version(version: TSCUtility.Version(1, 0, 0), - title: nil, - summary: nil, - manifests: [toolsVersion: mockManifest], - defaultToolsVersion: toolsVersion, - verifiedCompatibility: nil, - license: nil, - author: nil, - signer: nil, - createdAt: nil) + let mockVersion = PackageCollectionsModel.Package.Version( + version: TSCUtility.Version(1, 0, 0), + title: nil, + summary: nil, + manifests: [toolsVersion: mockManifest], + defaultToolsVersion: toolsVersion, + verifiedCompatibility: nil, + license: nil, + author: nil, + signer: nil, + createdAt: nil + ) let url = "https://packages.mock/\(UUID().uuidString)" - let mockPackage = PackageCollectionsModel.Package(identity: .init(urlString: url), - location: url, - summary: UUID().uuidString, - keywords: [UUID().uuidString, UUID().uuidString], - versions: [mockVersion], - watchersCount: nil, - readmeURL: nil, - license: nil, - authors: nil, - languages: nil) - - let mockCollection = PackageCollectionsModel.Collection(source: .init(type: .json, url: "https://feed.mock/\(UUID().uuidString)"), - name: UUID().uuidString, - overview: UUID().uuidString, - keywords: [UUID().uuidString, UUID().uuidString], - packages: [mockPackage], - createdAt: Date(), - createdBy: nil, - signature: nil) - - let mockCollection2 = PackageCollectionsModel.Collection(source: .init(type: .json, url: "https://feed.mock/\(UUID().uuidString)"), - name: UUID().uuidString, - overview: UUID().uuidString, - keywords: [UUID().uuidString, UUID().uuidString], - packages: [mockPackage], - createdAt: Date(), - createdBy: nil, - signature: nil) + let mockPackage = PackageCollectionsModel.Package( + identity: .init(urlString: url), + location: url, + summary: UUID().uuidString, + keywords: [UUID().uuidString, UUID().uuidString], + versions: [mockVersion], + watchersCount: nil, + readmeURL: nil, + license: nil, + authors: nil, + languages: nil + ) + + let mockCollection = PackageCollectionsModel.Collection( + source: .init(type: .json, url: "https://feed.mock/\(UUID().uuidString)"), + name: UUID().uuidString, + overview: UUID().uuidString, + keywords: [UUID().uuidString, UUID().uuidString], + packages: [mockPackage], + createdAt: Date(), + createdBy: nil, + signature: nil + ) + + let mockCollection2 = PackageCollectionsModel.Collection( + source: .init(type: .json, url: "https://feed.mock/\(UUID().uuidString)"), + name: UUID().uuidString, + overview: UUID().uuidString, + keywords: [UUID().uuidString, UUID().uuidString], + packages: [mockPackage], + createdAt: Date(), + createdBy: nil, + signature: nil + ) let expectedCollections = [mockCollection, mockCollection2] let expectedCollectionsIdentifiers = expectedCollections.map { $0.identifier }.sorted() @@ -634,11 +674,11 @@ class PackageIndexAndCollectionsTests: XCTestCase { let packageIndex = BrokenPackageIndex() let indexAndCollections = PackageIndexAndCollections(index: packageIndex, collections: packageCollections, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try indexAndCollections.close()) } - + for collection in mockCollections { _ = try await indexAndCollections.addCollection(collection.source, trustConfirmationProvider: { _, cb in cb(true) }) } - + // both index and collections do { let searchResult = try await indexAndCollections.findPackages(mockPackage.identity.description, in: .both(collections: nil)) @@ -647,7 +687,7 @@ class PackageIndexAndCollectionsTests: XCTestCase { // Results come from collections since index is broken XCTAssertEqual(searchResult.items.first?.indexes, [], "indexes should match") } - + // index only do { await XCTAssertAsyncThrowsError(try await indexAndCollections.findPackages(mockPackage.identity.description, in: .index)) { error in @@ -656,7 +696,7 @@ class PackageIndexAndCollectionsTests: XCTestCase { } } } - + // collections only do { let searchResult = try await indexAndCollections.findPackages(mockPackage.identity.description, in: .collections(nil)) @@ -676,7 +716,7 @@ private func makePackageCollections( let configuration = PackageCollections.Configuration() let collectionProviders = [PackageCollectionsModel.CollectionSourceType.json: MockCollectionsProvider(mockCollections)] let metadataProvider = metadataProvider - + return PackageCollections( configuration: configuration, fileSystem: localFileSystem, @@ -692,7 +732,7 @@ private struct MockPackageIndex: PackageIndexProtocol { let url: URL private let packages: [PackageCollectionsModel.Package] - + init( url: URL = "https://mock-package-index", packages: [PackageCollectionsModel.Package] = [] @@ -713,11 +753,11 @@ private struct MockPackageIndex: PackageIndexProtocol { func findPackages( _ query: String - ) async throws -> PackageCollectionsModel.PackageSearchResult{ + ) async throws -> PackageCollectionsModel.PackageSearchResult { let items = self.packages.filter { $0.identity.description.contains(query) } return PackageCollectionsModel.PackageSearchResult(items: items.map { .init(package: $0, collections: [], indexes: [self.url]) }) } - + func listPackages( offset: Int, limit: Int @@ -737,7 +777,7 @@ private struct MockPackageIndex: PackageIndexProtocol { private struct BrokenPackageIndex: PackageIndexProtocol { let isEnabled = true - + func getPackageMetadata( identity: PackageIdentity, location: String? @@ -750,13 +790,13 @@ private struct BrokenPackageIndex: PackageIndexProtocol { ) async throws -> PackageCollectionsModel.PackageSearchResult { throw TerribleThing() } - + func listPackages( offset: Int, limit: Int ) async throws -> PackageCollectionsModel.PaginatedPackageList { throw TerribleThing() } - + struct TerribleThing: Error {} } diff --git a/Tests/PackageCollectionsTests/PackageIndexConfigurationTests.swift b/Tests/PackageCollectionsTests/PackageIndexConfigurationTests.swift index 56db6fead40..9c14899575f 100644 --- a/Tests/PackageCollectionsTests/PackageIndexConfigurationTests.swift +++ b/Tests/PackageCollectionsTests/PackageIndexConfigurationTests.swift @@ -18,39 +18,39 @@ final class PackageIndexConfigurationTests: XCTestCase { func testSaveAndLoad() throws { let url = URL("https://package-index.test") let configuration = PackageIndexConfiguration(url: url) - + let fileSystem = InMemoryFileSystem() let storage = PackageIndexConfigurationStorage(path: try fileSystem.swiftPMConfigurationDirectory.appending("index.json"), fileSystem: fileSystem) try storage.save(configuration) - + let loadedConfiguration = try storage.load() XCTAssertEqual(loadedConfiguration, configuration) } - + func testLoad_fileDoesNotExist() throws { let fileSystem = InMemoryFileSystem() let storage = PackageIndexConfigurationStorage(path: try fileSystem.swiftPMConfigurationDirectory.appending("index.json"), fileSystem: fileSystem) let configuration = try storage.load() XCTAssertNil(configuration.url) } - + func testLoad_urlOnly() throws { let url = URL("https://package-index.test") let configJSON = """ - { - "index": { - "url": "\(url.absoluteString)" + { + "index": { + "url": "\(url.absoluteString)" + } } - } - """ - + """ + let fileSystem = InMemoryFileSystem() let configPath = try fileSystem.swiftPMConfigurationDirectory.appending("index.json") if !fileSystem.exists(configPath.parentDirectory, followSymlink: false) { try fileSystem.createDirectory(configPath.parentDirectory, recursive: true) } try fileSystem.writeFileContents(configPath, string: configJSON) - + let storage = PackageIndexConfigurationStorage(path: configPath, fileSystem: fileSystem) let configuration = try storage.load() XCTAssertEqual(configuration.url, url) diff --git a/Tests/PackageCollectionsTests/PackageIndexTests.swift b/Tests/PackageCollectionsTests/PackageIndexTests.swift index 4a619b4635a..ae27264b602 100644 --- a/Tests/PackageCollectionsTests/PackageIndexTests.swift +++ b/Tests/PackageCollectionsTests/PackageIndexTests.swift @@ -22,7 +22,7 @@ class PackageIndexTests: XCTestCase { let url = URL("https://package-index.test") var configuration = PackageIndexConfiguration(url: url, disableCache: true) configuration.enabled = true - + let repoURL = SourceControlURL("https://github.com/octocat/Hello-World.git") let packageIdentity = PackageIdentity(url: repoURL) let package = makeMockPackage(id: "test-package") @@ -30,59 +30,65 @@ class PackageIndexTests: XCTestCase { switch (request.method, request.url) { case (.get, url.appendingPathComponent("packages").appendingPathComponent(packageIdentity.description)): let data = try! JSONEncoder.makeWithDefaults().encode(package) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method and url should match") } } - + let httpClient = LegacyHTTPClient(handler: handler) httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none - + let index = PackageIndex(configuration: configuration, customHTTPClient: httpClient, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + let metadata = try await index.getPackageMetadata(identity: .init(url: repoURL), location: repoURL.absoluteString) XCTAssertEqual(metadata.package.identity, package.identity) XCTAssert(metadata.collections.isEmpty) XCTAssertNotNil(metadata.provider) } - + func testGetPackageMetadata_featureDisabled() async { let url = URL("https://package-index.test") var configuration = PackageIndexConfiguration(url: url, disableCache: true) configuration.enabled = false - + let index = PackageIndex(configuration: configuration, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + let repoURL = SourceControlURL("https://github.com/octocat/Hello-World.git") await XCTAssertAsyncThrowsError(try await index.getPackageMetadata(identity: .init(url: repoURL), location: repoURL.absoluteString)) { error in XCTAssertEqual(error as? PackageIndexError, .featureDisabled) } } - + func testGetPackageMetadata_notConfigured() async { var configuration = PackageIndexConfiguration(url: nil, disableCache: true) configuration.enabled = true - + let index = PackageIndex(configuration: configuration, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + let repoURL = SourceControlURL("https://github.com/octocat/Hello-World.git") await XCTAssertAsyncThrowsError(try await index.getPackageMetadata(identity: .init(url: repoURL), location: repoURL.absoluteString)) { error in XCTAssertEqual(error as? PackageIndexError, .notConfigured) } } - + func testFindPackages() async throws { let url = URL("https://package-index.test") var configuration = PackageIndexConfiguration(url: url, searchResultMaxItemsCount: 10, disableCache: true) configuration.enabled = true - + let packages = (0..<3).map { packageIndex -> PackageCollectionsModel.Package in makeMockPackage(id: "package-\(packageIndex)") } @@ -91,21 +97,27 @@ class PackageIndexTests: XCTestCase { switch (request.method, request.url) { case (.get, URL(string: url.appendingPathComponent("search").absoluteString + "?q=\(query)")!): let data = try! JSONEncoder.makeWithDefaults().encode(packages) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method and url should match") } } - + let httpClient = LegacyHTTPClient(handler: handler) httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none - + let index = PackageIndex(configuration: configuration, customHTTPClient: httpClient, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + let result = try await index.findPackages(query) XCTAssertEqual(result.items.count, packages.count) for (i, item) in result.items.enumerated() { @@ -114,12 +126,12 @@ class PackageIndexTests: XCTestCase { XCTAssertEqual(item.indexes, [url]) } } - + func testFindPackages_resultsLimit() async throws { let url = URL("https://package-index.test") var configuration = PackageIndexConfiguration(url: url, searchResultMaxItemsCount: 3, disableCache: true) configuration.enabled = true - + // This is larger than searchResultMaxItemsCount let packages = (0..<5).map { packageIndex -> PackageCollectionsModel.Package in makeMockPackage(id: "package-\(packageIndex)") @@ -129,21 +141,27 @@ class PackageIndexTests: XCTestCase { switch (request.method, request.url) { case (.get, URL(string: url.appendingPathComponent("search").absoluteString + "?q=\(query)")!): let data = try! JSONEncoder.makeWithDefaults().encode(packages) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method and url should match") } } - + let httpClient = LegacyHTTPClient(handler: handler) httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none - + let index = PackageIndex(configuration: configuration, customHTTPClient: httpClient, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + let result = try await index.findPackages(query) XCTAssertEqual(result.items.count, configuration.searchResultMaxItemsCount) for (i, item) in result.items.enumerated() { @@ -152,37 +170,37 @@ class PackageIndexTests: XCTestCase { XCTAssertEqual(item.indexes, [url]) } } - + func testFindPackages_featureDisabled() async { let url = URL("https://package-index.test") var configuration = PackageIndexConfiguration(url: url, disableCache: true) configuration.enabled = false - + let index = PackageIndex(configuration: configuration, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + await XCTAssertAsyncThrowsError(try await index.findPackages("foobar")) { error in XCTAssertEqual(error as? PackageIndexError, .featureDisabled) } } - + func testFindPackages_notConfigured() async { var configuration = PackageIndexConfiguration(url: nil, disableCache: true) configuration.enabled = true - + let index = PackageIndex(configuration: configuration, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + await XCTAssertAsyncThrowsError(try await index.findPackages("foobar")) { error in XCTAssertEqual(error as? PackageIndexError, .notConfigured) } } - + func testListPackages() async throws { let url = URL("https://package-index.test") var configuration = PackageIndexConfiguration(url: url, disableCache: true) configuration.enabled = true - + let offset = 4 let limit = 3 let total = 20 @@ -194,58 +212,64 @@ class PackageIndexTests: XCTestCase { case (.get, URL(string: url.appendingPathComponent("packages").absoluteString + "?offset=\(offset)&limit=\(limit)")!): let response = PackageIndex.ListResponse(items: packages, total: total) let data = try! JSONEncoder.makeWithDefaults().encode(response) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method and url should match") } } - + let httpClient = LegacyHTTPClient(handler: handler) httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none - + let index = PackageIndex(configuration: configuration, customHTTPClient: httpClient, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + let result = try await index.listPackages(offset: offset, limit: limit) XCTAssertEqual(result.items.count, packages.count) XCTAssertEqual(result.offset, offset) XCTAssertEqual(result.limit, limit) XCTAssertEqual(result.total, total) } - + func testListPackages_featureDisabled() async { let url = URL("https://package-index.test") var configuration = PackageIndexConfiguration(url: url, disableCache: true) configuration.enabled = false - + let index = PackageIndex(configuration: configuration, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + await XCTAssertAsyncThrowsError(try await index.listPackages(offset: 0, limit: 10)) { error in XCTAssertEqual(error as? PackageIndexError, .featureDisabled) } } - + func testListPackages_notConfigured() async { var configuration = PackageIndexConfiguration(url: nil, disableCache: true) configuration.enabled = true - + let index = PackageIndex(configuration: configuration, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + await XCTAssertAsyncThrowsError(try await index.listPackages(offset: 0, limit: 10)) { error in XCTAssertEqual(error as? PackageIndexError, .notConfigured) } } - + func testAsPackageMetadataProvider() async throws { let url = URL("https://package-index.test") var configuration = PackageIndexConfiguration(url: url, disableCache: true) configuration.enabled = true - + let repoURL = SourceControlURL("https://github.com/octocat/Hello-World.git") let packageIdentity = PackageIdentity(url: repoURL) let package = makeMockPackage(id: "test-package") @@ -253,46 +277,52 @@ class PackageIndexTests: XCTestCase { switch (request.method, request.url) { case (.get, url.appendingPathComponent("packages").appendingPathComponent(packageIdentity.description)): let data = try! JSONEncoder.makeWithDefaults().encode(package) - completion(.success(.init(statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), - body: data))) + completion( + .success( + .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "\(data.count)")]), + body: data + ) + ) + ) default: XCTFail("method and url should match") } } - + let httpClient = LegacyHTTPClient(handler: handler) httpClient.configuration.circuitBreakerStrategy = .none httpClient.configuration.retryStrategy = .none - + let index = PackageIndex(configuration: configuration, customHTTPClient: httpClient, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + let metadata = try await index.syncGet(identity: .init(url: repoURL), location: repoURL.absoluteString) XCTAssertEqual(metadata.summary, package.summary) } - + func testAsGetPackageMetadataProvider_featureDisabled() async { let url = URL("https://package-index.test") var configuration = PackageIndexConfiguration(url: url, disableCache: true) configuration.enabled = false - + let index = PackageIndex(configuration: configuration, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + let repoURL = SourceControlURL("https://github.com/octocat/Hello-World.git") await XCTAssertAsyncThrowsError(try await index.syncGet(identity: .init(url: repoURL), location: repoURL.absoluteString)) { error in XCTAssertEqual(error as? PackageIndexError, .featureDisabled) } } - + func testAsGetPackageMetadataProvider_notConfigured() async { var configuration = PackageIndexConfiguration(url: nil, disableCache: true) configuration.enabled = true - + let index = PackageIndex(configuration: configuration, callbackQueue: .sharedConcurrent, observabilityScope: ObservabilitySystem.NOOP) defer { XCTAssertNoThrow(try index.close()) } - + let repoURL = SourceControlURL("https://github.com/octocat/Hello-World.git") await XCTAssertAsyncThrowsError(try await index.syncGet(identity: .init(url: repoURL), location: repoURL.absoluteString)) { error in XCTAssertEqual(error as? PackageIndexError, .notConfigured) diff --git a/Tests/PackageCollectionsTests/TrieTests.swift b/Tests/PackageCollectionsTests/TrieTests.swift index 35d1d5ae08d..ce61e5540e4 100644 --- a/Tests/PackageCollectionsTests/TrieTests.swift +++ b/Tests/PackageCollectionsTests/TrieTests.swift @@ -42,7 +42,7 @@ import Testing #expect(try trie.find(word: "brown") == [1, 2]) #expect(try trie.find(word: "blocked") == [2]) - #expect(throws:NotFoundError.self) { + #expect(throws: NotFoundError.self) { try trie.find(word: "fo") } } @@ -201,7 +201,7 @@ import Testing let docCount = 100 await withTaskGroup { group in - for i in 0 ..< docCount { + for i in 0.. [PackageCollectionsModel.CollectionSource] { +func makeMockSources(count: Int = Int.random(in: 5...10)) -> [PackageCollectionsModel.CollectionSource] { let isTrusted: [Bool?] = [true, false, nil] - return (0 ..< count).map { index in + return (0.. [PackageCollectionsModel.Collection] { - (0 ..< count).map { collectionIndex in - let packages = (0 ..< Int.random(in: min(5, maxPackages) ... maxPackages)).map { packageIndex -> PackageCollectionsModel.Package in +func makeMockCollections(count: Int = Int.random(in: 50...100), maxPackages: Int = 50, signed: Bool = true) -> [PackageCollectionsModel.Collection] { + (0.. PackageCollectionsModel.Package in makeMockPackage(id: "package-\(packageIndex)") } @@ -53,39 +53,47 @@ func makeMockCollections(count: Int = Int.random(in: 50 ... 100), maxPackages: I ) } - return PackageCollectionsModel.Collection(source: .init(type: .json, url: "https://feed-\(collectionIndex)"), - name: "collection \(collectionIndex)", - overview: "collection \(collectionIndex) description", - keywords: (0 ..< Int.random(in: 1 ... 3)).map { "keyword \($0)" }, - packages: packages, - createdAt: Date(), - createdBy: PackageCollectionsModel.Collection.Author(name: "Jane Doe"), - signature: signature) + return PackageCollectionsModel.Collection( + source: .init(type: .json, url: "https://feed-\(collectionIndex)"), + name: "collection \(collectionIndex)", + overview: "collection \(collectionIndex) description", + keywords: (0.. PackageCollectionsModel.Package { - let versions = (0 ..< Int.random(in: 1 ... 3)).map { versionIndex -> PackageCollectionsModel.Package.Version in - let targets = (0 ..< Int.random(in: 1 ... 5)).map { - PackageCollectionsModel.Target(name: "\(id)-target-\($0)", - moduleName: "module-\(id)-target-\($0)") + let versions = (0.. PackageCollectionsModel.Package.Version in + let targets = (0.. PackageCollectionsModel.Package { let licenseType = PackageCollectionsModel.LicenseType.allCases.randomElement()! let license = PackageCollectionsModel.License(type: licenseType, url: "http://\(licenseType).license") - return PackageCollectionsModel.Package.Version(version: TSCUtility.Version(versionIndex, 0, 0), - title: nil, - summary: "\(versionIndex) description", - manifests: manifests, - defaultToolsVersion: toolsVersion, - verifiedCompatibility: verifiedCompatibility, - license: license, - author: nil, - signer: nil, - createdAt: Date()) + return PackageCollectionsModel.Package.Version( + version: TSCUtility.Version(versionIndex, 0, 0), + title: nil, + summary: "\(versionIndex) description", + manifests: manifests, + defaultToolsVersion: toolsVersion, + verifiedCompatibility: verifiedCompatibility, + license: license, + author: nil, + signer: nil, + createdAt: Date() + ) } - return PackageCollectionsModel.Package(identity: PackageIdentity.plain("test-\(id).\(id)"), - location: "https://\(id)", - summary: "\(id) description", - keywords: (0 ..< Int.random(in: 1 ... 3)).map { "keyword \($0)" }, - versions: versions, - watchersCount: Int.random(in: 1 ... 1000), - readmeURL: "https://\(id)-readme", - license: PackageCollectionsModel.License(type: .Apache2_0, url: "https://\(id).license"), - authors: nil, - languages: nil) + return PackageCollectionsModel.Package( + identity: PackageIdentity.plain("test-\(id).\(id)"), + location: "https://\(id)", + summary: "\(id) description", + keywords: (0.. PackageCollectionsModel.PackageBasicMetadata { - return .init(summary: UUID().uuidString, - keywords: (0 ..< Int.random(in: 1 ... 3)).map { "keyword \($0)" }, - versions: (0 ..< Int.random(in: 1 ... 10)).map { .init( - version: TSCUtility.Version($0, 0, 0), - title: "title \($0)", - summary: "description \($0)", - author: nil, - createdAt: Date() - )}, - watchersCount: Int.random(in: 0 ... 50), - readmeURL: "https://package-readme", - license: PackageCollectionsModel.License(type: .Apache2_0, url: "https://package-license"), - authors: (0 ..< Int.random(in: 1 ... 10)).map { .init(username: "\($0)", url: nil, service: nil) }, - languages: ["Swift"]) + return .init( + summary: UUID().uuidString, + keywords: (0.. PackageCollections.Storage { diff --git a/Tests/PackageDescriptionTests/VersionTests.swift b/Tests/PackageDescriptionTests/VersionTests.swift index d80d22582f6..034cd62e4ee 100644 --- a/Tests/PackageDescriptionTests/VersionTests.swift +++ b/Tests/PackageDescriptionTests/VersionTests.swift @@ -14,7 +14,7 @@ import PackageDescription import XCTest class VersionTests: XCTestCase { - + func testVersionInitialization() { let v0 = Version(0, 0, 0, prereleaseIdentifiers: [], buildMetadataIdentifiers: []) XCTAssertEqual(v0.minor, 0) @@ -22,82 +22,82 @@ class VersionTests: XCTestCase { XCTAssertEqual(v0.patch, 0) XCTAssertEqual(v0.prereleaseIdentifiers, []) XCTAssertEqual(v0.buildMetadataIdentifiers, []) - + let v1 = Version(1, 1, 2, prereleaseIdentifiers: ["3", "5"], buildMetadataIdentifiers: ["8", "13"]) XCTAssertEqual(v1.minor, 1) XCTAssertEqual(v1.minor, 1) XCTAssertEqual(v1.patch, 2) XCTAssertEqual(v1.prereleaseIdentifiers, ["3", "5"]) XCTAssertEqual(v1.buildMetadataIdentifiers, ["8", "13"]) - + XCTAssertEqual( Version(3, 5, 8), Version(3, 5, 8, prereleaseIdentifiers: [], buildMetadataIdentifiers: []) ) - + XCTAssertEqual( Version(13, 21, 34, prereleaseIdentifiers: ["55"]), Version(13, 21, 34, prereleaseIdentifiers: ["55"], buildMetadataIdentifiers: []) ) - + XCTAssertEqual( Version(89, 144, 233, buildMetadataIdentifiers: ["377"]), Version(89, 144, 233, prereleaseIdentifiers: [], buildMetadataIdentifiers: ["377"]) ) } - + // Don't refactor out either `XCTAssertGreaterThan` or `XCTAssertFalse(<)`. // They may appear redundant, but they test different things. // `XCTAssertGreaterThan` tests the "true" path of `>` which is basically the "true" path of `<`. // `XCTAssertFalse(<)` tests the "false" path of `<`. func testVersionComparison() { - + // MARK: version core vs. version core - + XCTAssertGreaterThan(Version(2, 1, 1), Version(1, 2, 3)) XCTAssertGreaterThan(Version(1, 3, 1), Version(1, 2, 3)) XCTAssertGreaterThan(Version(1, 2, 4), Version(1, 2, 3)) - + XCTAssertFalse(Version(2, 1, 1) < Version(1, 2, 3)) XCTAssertFalse(Version(1, 3, 1) < Version(1, 2, 3)) XCTAssertFalse(Version(1, 2, 4) < Version(1, 2, 3)) - + // MARK: version core vs. version core + pre-release - + XCTAssertGreaterThan(Version(1, 2, 3), Version(1, 2, 3, prereleaseIdentifiers: [""])) XCTAssertGreaterThan(Version(1, 2, 3), Version(1, 2, 3, prereleaseIdentifiers: ["beta"])) XCTAssertLessThan(Version(1, 2, 2), Version(1, 2, 3, prereleaseIdentifiers: ["beta"])) - + XCTAssertFalse(Version(1, 2, 3) < Version(1, 2, 3, prereleaseIdentifiers: [""])) XCTAssertFalse(Version(1, 2, 3) < Version(1, 2, 3, prereleaseIdentifiers: ["beta"])) - + // MARK: version core + pre-release vs. version core + pre-release - + XCTAssertEqual(Version(1, 2, 3, prereleaseIdentifiers: [""]), Version(1, 2, 3, prereleaseIdentifiers: [""])) - + XCTAssertEqual(Version(1, 2, 3, prereleaseIdentifiers: ["beta"]), Version(1, 2, 3, prereleaseIdentifiers: ["beta"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["alpha"]), Version(1, 2, 3, prereleaseIdentifiers: ["beta"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["alpha1"]), Version(1, 2, 3, prereleaseIdentifiers: ["alpha2"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["alpha"]), Version(1, 2, 3, prereleaseIdentifiers: ["alpha-"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["beta", "alpha"]), Version(1, 2, 3, prereleaseIdentifiers: ["beta", "beta"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["alpha", "beta"]), Version(1, 2, 3, prereleaseIdentifiers: ["beta", "alpha"])) - + XCTAssertEqual(Version(1, 2, 3, prereleaseIdentifiers: ["1"]), Version(1, 2, 3, prereleaseIdentifiers: ["1"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["1"]), Version(1, 2, 3, prereleaseIdentifiers: ["2"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["1", "1"]), Version(1, 2, 3, prereleaseIdentifiers: ["1", "2"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["1", "2"]), Version(1, 2, 3, prereleaseIdentifiers: ["2", "1"])) - + XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["123"]), Version(1, 2, 3, prereleaseIdentifiers: ["123alpha"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["223"]), Version(1, 2, 3, prereleaseIdentifiers: ["123alpha"])) - + // MARK: version core vs. version core + build metadata - + XCTAssertEqual(Version(1, 2, 3), Version(1, 2, 3, buildMetadataIdentifiers: [""])) XCTAssertEqual(Version(1, 2, 3), Version(1, 2, 3, buildMetadataIdentifiers: ["beta"])) XCTAssertLessThan(Version(1, 2, 2), Version(1, 2, 3, buildMetadataIdentifiers: ["beta"])) - + // MARK: version core + pre-release vs. version core + build metadata - + XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: [""]), Version(1, 2, 3, buildMetadataIdentifiers: [""])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["beta"]), Version(1, 2, 3, buildMetadataIdentifiers: ["alpha"])) XCTAssertLessThan(Version(1, 2, 3, prereleaseIdentifiers: ["alpha"]), Version(1, 2, 3, buildMetadataIdentifiers: ["beta"])) @@ -112,51 +112,51 @@ class VersionTests: XCTestCase { XCTAssertGreaterThan(Version(2, 2, 3, prereleaseIdentifiers: [""]), Version(1, 2, 3, buildMetadataIdentifiers: [""])) XCTAssertGreaterThan(Version(1, 3, 3, prereleaseIdentifiers: ["alpha"]), Version(1, 2, 3, buildMetadataIdentifiers: ["beta"])) XCTAssertGreaterThan(Version(1, 2, 4, prereleaseIdentifiers: ["223"]), Version(1, 2, 3, buildMetadataIdentifiers: ["123alpha"])) - + XCTAssertFalse(Version(2, 2, 3, prereleaseIdentifiers: [""]) < Version(1, 2, 3, buildMetadataIdentifiers: [""])) XCTAssertFalse(Version(1, 3, 3, prereleaseIdentifiers: ["alpha"]) < Version(1, 2, 3, buildMetadataIdentifiers: ["beta"])) XCTAssertFalse(Version(1, 2, 4, prereleaseIdentifiers: ["223"]) < Version(1, 2, 3, buildMetadataIdentifiers: ["123alpha"])) - + // MARK: version core + build metadata vs. version core + build metadata - + XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: [""]), Version(1, 2, 3, buildMetadataIdentifiers: [""])) - + XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["beta"]), Version(1, 2, 3, buildMetadataIdentifiers: ["beta"])) XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["alpha"]), Version(1, 2, 3, buildMetadataIdentifiers: ["beta"])) XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["alpha1"]), Version(1, 2, 3, buildMetadataIdentifiers: ["alpha2"])) XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["alpha"]), Version(1, 2, 3, buildMetadataIdentifiers: ["alpha-"])) XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["beta", "alpha"]), Version(1, 2, 3, buildMetadataIdentifiers: ["beta", "beta"])) XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["alpha", "beta"]), Version(1, 2, 3, buildMetadataIdentifiers: ["beta", "alpha"])) - + XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["1"]), Version(1, 2, 3, buildMetadataIdentifiers: ["1"])) XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["1"]), Version(1, 2, 3, buildMetadataIdentifiers: ["2"])) XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["1", "1"]), Version(1, 2, 3, buildMetadataIdentifiers: ["1", "2"])) XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["1", "2"]), Version(1, 2, 3, buildMetadataIdentifiers: ["2", "1"])) - + XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["123"]), Version(1, 2, 3, buildMetadataIdentifiers: ["123alpha"])) XCTAssertEqual(Version(1, 2, 3, buildMetadataIdentifiers: ["223"]), Version(1, 2, 3, buildMetadataIdentifiers: ["123alpha"])) - + // MARK: version core vs. version core + pre-release + build metadata - + XCTAssertGreaterThan(Version(1, 2, 3), Version(1, 2, 3, prereleaseIdentifiers: [""], buildMetadataIdentifiers: [""])) XCTAssertGreaterThan(Version(1, 2, 3), Version(1, 2, 3, prereleaseIdentifiers: [""], buildMetadataIdentifiers: ["123alpha"])) XCTAssertGreaterThan(Version(1, 2, 3), Version(1, 2, 3, prereleaseIdentifiers: ["alpha"], buildMetadataIdentifiers: ["alpha"])) XCTAssertGreaterThan(Version(1, 2, 3), Version(1, 2, 3, prereleaseIdentifiers: ["beta"], buildMetadataIdentifiers: ["123"])) XCTAssertLessThan(Version(1, 2, 2), Version(1, 2, 3, prereleaseIdentifiers: ["beta"], buildMetadataIdentifiers: ["alpha", "beta"])) XCTAssertLessThan(Version(1, 2, 2), Version(1, 2, 3, prereleaseIdentifiers: ["beta"], buildMetadataIdentifiers: ["alpha-"])) - + XCTAssertFalse(Version(1, 2, 3) < Version(1, 2, 3, prereleaseIdentifiers: [""], buildMetadataIdentifiers: [""])) XCTAssertFalse(Version(1, 2, 3) < Version(1, 2, 3, prereleaseIdentifiers: [""], buildMetadataIdentifiers: ["123alpha"])) XCTAssertFalse(Version(1, 2, 3) < Version(1, 2, 3, prereleaseIdentifiers: ["alpha"], buildMetadataIdentifiers: ["alpha"])) XCTAssertFalse(Version(1, 2, 3) < Version(1, 2, 3, prereleaseIdentifiers: ["beta"], buildMetadataIdentifiers: ["123"])) - + // MARK: version core + pre-release vs. version core + pre-release + build metadata - + XCTAssertEqual( Version(1, 2, 3, prereleaseIdentifiers: [""]), Version(1, 2, 3, prereleaseIdentifiers: [""], buildMetadataIdentifiers: [""]) ) - + XCTAssertEqual( Version(1, 2, 3, prereleaseIdentifiers: ["beta"]), Version(1, 2, 3, prereleaseIdentifiers: ["beta"], buildMetadataIdentifiers: [""]) @@ -181,7 +181,7 @@ class VersionTests: XCTestCase { Version(1, 2, 3, prereleaseIdentifiers: ["alpha", "beta"]), Version(1, 2, 3, prereleaseIdentifiers: ["beta", "alpha"], buildMetadataIdentifiers: ["alpha-"]) ) - + XCTAssertEqual( Version(1, 2, 3, prereleaseIdentifiers: ["1"]), Version(1, 2, 3, prereleaseIdentifiers: ["1"], buildMetadataIdentifiers: [""]) @@ -198,7 +198,7 @@ class VersionTests: XCTestCase { Version(1, 2, 3, prereleaseIdentifiers: ["1", "2"]), Version(1, 2, 3, prereleaseIdentifiers: ["2", "1"], buildMetadataIdentifiers: ["alpha", "beta"]) ) - + XCTAssertLessThan( Version(1, 2, 3, prereleaseIdentifiers: ["123"]), Version(1, 2, 3, prereleaseIdentifiers: ["123alpha"], buildMetadataIdentifiers: ["-alpha"]) @@ -207,14 +207,14 @@ class VersionTests: XCTestCase { Version(1, 2, 3, prereleaseIdentifiers: ["223"]), Version(1, 2, 3, prereleaseIdentifiers: ["123alpha"], buildMetadataIdentifiers: ["123"]) ) - + // MARK: version core + pre-release + build metadata vs. version core + pre-release + build metadata - + XCTAssertEqual( Version(1, 2, 3, prereleaseIdentifiers: [""], buildMetadataIdentifiers: [""]), Version(1, 2, 3, prereleaseIdentifiers: [""], buildMetadataIdentifiers: [""]) ) - + XCTAssertEqual( Version(1, 2, 3, prereleaseIdentifiers: ["beta"], buildMetadataIdentifiers: ["123"]), Version(1, 2, 3, prereleaseIdentifiers: ["beta"], buildMetadataIdentifiers: [""]) @@ -239,7 +239,7 @@ class VersionTests: XCTestCase { Version(1, 2, 3, prereleaseIdentifiers: ["alpha", "beta"], buildMetadataIdentifiers: [""]), Version(1, 2, 3, prereleaseIdentifiers: ["beta", "alpha"], buildMetadataIdentifiers: ["alpha-"]) ) - + XCTAssertEqual( Version(1, 2, 3, prereleaseIdentifiers: ["1"], buildMetadataIdentifiers: ["alpha-"]), Version(1, 2, 3, prereleaseIdentifiers: ["1"], buildMetadataIdentifiers: [""]) @@ -256,7 +256,7 @@ class VersionTests: XCTestCase { Version(1, 2, 3, prereleaseIdentifiers: ["1", "2"], buildMetadataIdentifiers: ["alpha"]), Version(1, 2, 3, prereleaseIdentifiers: ["2", "1"], buildMetadataIdentifiers: ["alpha", "beta"]) ) - + XCTAssertLessThan( Version(1, 2, 3, prereleaseIdentifiers: ["123"], buildMetadataIdentifiers: ["123alpha"]), Version(1, 2, 3, prereleaseIdentifiers: ["123alpha"], buildMetadataIdentifiers: ["-alpha"]) @@ -265,13 +265,13 @@ class VersionTests: XCTestCase { Version(1, 2, 3, prereleaseIdentifiers: ["223"], buildMetadataIdentifiers: ["123alpha"]), Version(1, 2, 3, prereleaseIdentifiers: ["123alpha"], buildMetadataIdentifiers: ["123"]) ) - + } - + func testCustomConversionFromVersionToString() { - + // MARK: Version.description - + XCTAssertEqual(Version(0, 0, 0).description, "0.0.0" as String) XCTAssertEqual(Version(1, 2, 3).description, "1.2.3" as String) XCTAssertEqual(Version(1, 2, 3, prereleaseIdentifiers: [""]).description, "1.2.3-" as String) @@ -292,9 +292,9 @@ class VersionTests: XCTestCase { XCTAssertEqual(Version(1, 2, 3, prereleaseIdentifiers: ["beta", "1"], buildMetadataIdentifiers: ["alpha", "1"]).description, "1.2.3-beta.1+alpha.1" as String) XCTAssertEqual(Version(1, 2, 3, prereleaseIdentifiers: ["beta", "", "1"], buildMetadataIdentifiers: ["alpha", "", "1"]).description, "1.2.3-beta..1+alpha..1" as String) XCTAssertEqual(Version(1, 2, 3, prereleaseIdentifiers: ["be-ta", "", "1"], buildMetadataIdentifiers: ["al-pha", "", "1"]).description, "1.2.3-be-ta..1+al-pha..1" as String) - + // MARK: String interpolation - + XCTAssertEqual("\(Version(0, 0, 0))", "0.0.0" as String) XCTAssertEqual("\(Version(1, 2, 3))", "1.2.3" as String) XCTAssertEqual("\(Version(1, 2, 3, prereleaseIdentifiers: [""]))", "1.2.3-" as String) @@ -315,15 +315,15 @@ class VersionTests: XCTestCase { XCTAssertEqual("\(Version(1, 2, 3, prereleaseIdentifiers: ["beta", "1"], buildMetadataIdentifiers: ["alpha", "1"]))", "1.2.3-beta.1+alpha.1" as String) XCTAssertEqual("\(Version(1, 2, 3, prereleaseIdentifiers: ["beta", "", "1"], buildMetadataIdentifiers: ["alpha", "", "1"]))", "1.2.3-beta..1+alpha..1" as String) XCTAssertEqual("\(Version(1, 2, 3, prereleaseIdentifiers: ["be-ta", "", "1"], buildMetadataIdentifiers: ["al-pha", "", "1"]))", "1.2.3-be-ta..1+al-pha..1" as String) - + } - + func testLosslessConversionFromStringToVersion() { - + // We use type coercion `as String` in `Version(_:)` because there is a pair of overloaded initializers: `init(_ version: Version)` and `init?(_ versionString: String)`, and we want to test the latter in this function. - + // MARK: Well-formed version core - + XCTAssertNotNil(Version("0.0.0" as String)) XCTAssertEqual(Version("0.0.0" as String), Version(0, 0, 0)) @@ -352,7 +352,7 @@ class VersionTests: XCTestCase { XCTAssertNotNil(Version("55.89.144-beta.1" as String)) XCTAssertEqual(Version("55.89.144-beta.1" as String), Version(55, 89, 144, prereleaseIdentifiers: ["beta", "1"])) - + XCTAssertNotNil(Version("89.144.233-a.whole..lot.of.pre-release.identifiers" as String)) XCTAssertEqual(Version("89.144.233-a.whole..lot.of.pre-release.identifiers" as String), Version(89, 144, 233, prereleaseIdentifiers: ["a", "whole", "", "lot", "of", "pre-release", "identifiers"])) @@ -360,7 +360,7 @@ class VersionTests: XCTestCase { XCTAssertEqual(Version("144.233.377-" as String), Version(144, 233, 377, prereleaseIdentifiers: [""])) // MARK: Well-formed version core, malformed pre-release identifiers - + XCTAssertNil(Version("233.377.610-hello world" as String)) // MARK: Malformed version core, well-formed pre-release identifiers @@ -370,79 +370,79 @@ class VersionTests: XCTestCase { XCTAssertNil(Version("1597.2584.4181.6765-a.whole.lot.of.pre-release.identifiers" as String)) XCTAssertNil(Version("6 x 9 = 42-" as String)) XCTAssertNil(Version("forty-two" as String)) - + // MARK: Well-formed version core, well-formed build metadata identifiers - + XCTAssertNotNil(Version("0.0.0+some-metadata" as String)) XCTAssertEqual(Version("0.0.0+some-metadata" as String), Version(0, 0, 0, buildMetadataIdentifiers: ["some-metadata"])) - + XCTAssertNotNil(Version("4181.6765.10946+more.meta..more.data" as String)) XCTAssertEqual(Version("4181.6765.10946+more.meta..more.data" as String), Version(4181, 6765, 10946, buildMetadataIdentifiers: ["more", "meta", "", "more", "data"])) - + XCTAssertNotNil(Version("6765.10946.17711+-a-very--long---build-----metadata--------identifier-------------with---------------------many----------------------------------hyphens-------------------------------------------------------" as String)) XCTAssertEqual(Version("6765.10946.17711+-a-very--long---build-----metadata--------identifier-------------with---------------------many----------------------------------hyphens-------------------------------------------------------" as String), Version(6765, 10946, 17711, buildMetadataIdentifiers: ["-a-very--long---build-----metadata--------identifier-------------with---------------------many----------------------------------hyphens-------------------------------------------------------"])) - + XCTAssertNotNil(Version("10946.17711.28657+" as String)) XCTAssertEqual(Version("10946.17711.28657+" as String), Version(10946, 17711, 28657, buildMetadataIdentifiers: [""])) - + // MARK: Well-formed version core, malformed build metadata identifiers - + XCTAssertNil(Version("17711.28657.46368+hello world" as String)) XCTAssertNil(Version("28657.46368.75025+hello+world" as String)) - + // MARK: Malformed version core, well-formed build metadata identifiers - + XCTAssertNil(Version("121393+Hello.world--------" as String)) XCTAssertNil(Version("121393.196418+half-life.3" as String)) XCTAssertNil(Version("196418.317811.514229.832040+a.whole.lot.of.build.metadata.identifiers" as String)) XCTAssertNil(Version("196418.317811.514229.832040+a.whole.lot.of.build.metadata.identifiers" as String)) XCTAssertNil(Version("6 x 9 = 42+" as String)) XCTAssertNil(Version("forty two+a-very-long-build-metadata-identifier-with-many-hyphens" as String)) - + // MARK: Well-formed version core, well-formed pre-release identifiers, well-formed build metadata identifiers - + XCTAssertNotNil(Version("0.0.0-beta.-42+42-42.42" as String)) XCTAssertEqual(Version("0.0.0-beta.-42+42-42.42" as String), Version(0, 0, 0, prereleaseIdentifiers: ["beta", "-42"], buildMetadataIdentifiers: ["42-42", "42"])) - + // MARK: Well-formed version core, well-formed pre-release identifiers, malformed build metadata identifiers - + XCTAssertNil(Version("514229.832040.1346269-beta1+ " as String)) - + // MARK: Well-formed version core, malformed pre-release identifiers, well-formed build metadata identifiers - + XCTAssertNil(Version("832040.1346269.2178309-beta 1+-" as String)) - + // MARK: Well-formed version core, malformed pre-release identifiers, malformed build metadata identifiers - + XCTAssertNil(Version("1346269.2178309.3524578-beta 1++" as String)) - + // MARK: malformed version core, well-formed pre-release identifiers, well-formed build metadata identifiers - + XCTAssertNil(Version(" 832040.1346269.3524578-beta1+abc" as String)) - + // MARK: malformed version core, well-formed pre-release identifiers, malformed build metadata identifiers - + XCTAssertNil(Version("1346269.3524578.5702887-beta1+😀" as String)) - + // MARK: malformed version core, malformed pre-release identifiers, well-formed build metadata identifiers - + XCTAssertNil(Version("3524578.5702887.9227465-beta!@#$%^&*1+asdfghjkl123456789" as String)) - + // MARK: malformed version core, malformed pre-release identifiers, malformed build metadata identifiers - + XCTAssertNil(Version("5702887.9227465-bètá1+±" as String)) - + } - + func testExpressingVersionByStringLiteral() { - + // MARK: Well-formed version core - + XCTAssertEqual("0.0.0" as Version, Version(0, 0, 0)) XCTAssertEqual("1.1.2" as Version, Version(1, 1, 2)) - + // MARK: Malformed version core - + XCTAssertEqual("" as Version, Version(0, 0, 0)) XCTAssertEqual("3" as Version, Version(0, 0, 0)) XCTAssertEqual("3 5" as Version, Version(0, 0, 0)) @@ -456,41 +456,41 @@ class VersionTests: XCTestCase { XCTAssertEqual("21.34.55.89" as Version, Version(0, 0, 0)) XCTAssertEqual("6 x 9 = 42" as Version, Version(0, 0, 0)) XCTAssertEqual("forty two" as Version, Version(0, 0, 0)) - + // MARK: Well-formed version core, well-formed pre-release identifiers - + XCTAssertEqual("0.0.0-pre-alpha" as Version, Version(0, 0, 0, prereleaseIdentifiers: ["pre-alpha"])) XCTAssertEqual("55.89.144-beta.1" as Version, Version(55, 89, 144, prereleaseIdentifiers: ["beta", "1"])) XCTAssertEqual("89.144.233-a.whole..lot.of.pre-release.identifiers" as Version, Version(89, 144, 233, prereleaseIdentifiers: ["a", "whole", "", "lot", "of", "pre-release", "identifiers"])) XCTAssertEqual("144.233.377-" as Version, Version(144, 233, 377, prereleaseIdentifiers: [""])) - + // MARK: Well-formed version core, malformed pre-release identifiers - + XCTAssertEqual("233.377.610-hello world" as Version, Version(0, 0, 0)) - + // MARK: Malformed version core, well-formed pre-release identifiers - + XCTAssertEqual("-Hello.world--------" as Version, Version(0, 0, 0)) XCTAssertEqual("987-Hello.world--------" as Version, Version(0, 0, 0)) XCTAssertEqual("987.1597-half-life.3" as Version, Version(0, 0, 0)) XCTAssertEqual("1597.2584.4181.6765-a.whole.lot.of.pre-release.identifiers" as Version, Version(0, 0, 0)) XCTAssertEqual("6 x 9 = 42-" as Version, Version(0, 0, 0)) XCTAssertEqual("forty-two" as Version, Version(0, 0, 0)) - + // MARK: Well-formed version core, well-formed build metadata identifiers - + XCTAssertEqual("0.0.0+some-metadata" as Version, Version(0, 0, 0, buildMetadataIdentifiers: ["some-metadata"])) XCTAssertEqual("4181.6765.10946+more.meta..more.data" as Version, Version(4181, 6765, 10946, buildMetadataIdentifiers: ["more", "meta", "", "more", "data"])) XCTAssertEqual("6765.10946.17711+-a-very--long---build-----metadata--------identifier-------------with---------------------many----------------------------------hyphens-------------------------------------------------------" as Version, Version(6765, 10946, 17711, buildMetadataIdentifiers: ["-a-very--long---build-----metadata--------identifier-------------with---------------------many----------------------------------hyphens-------------------------------------------------------"])) XCTAssertEqual("10946.17711.28657+" as Version, Version(10946, 17711, 28657, buildMetadataIdentifiers: [""])) - + // MARK: Well-formed version core, malformed build metadata identifiers - + XCTAssertEqual("17711.28657.46368+hello world" as Version, Version(0, 0, 0)) XCTAssertEqual("28657.46368.75025+hello+world" as Version, Version(0, 0, 0)) - + // MARK: Malformed version core, well-formed build metadata identifiers - + XCTAssertEqual("+Hello.world--------" as Version, Version(0, 0, 0)) XCTAssertEqual("121393+Hello.world--------" as Version, Version(0, 0, 0)) XCTAssertEqual("121393.196418+half-life.3" as Version, Version(0, 0, 0)) @@ -498,50 +498,49 @@ class VersionTests: XCTestCase { XCTAssertEqual("196418.317811.514229.832040+a.whole.lot.of.build.metadata.identifiers" as Version, Version(0, 0, 0)) XCTAssertEqual("6 x 9 = 42+" as Version, Version(0, 0, 0)) XCTAssertEqual("forty two+a-very-long-build-metadata-identifier-with-many-hyphens" as Version, Version(0, 0, 0)) - + // MARK: Well-formed version core, well-formed pre-release identifiers, well-formed build metadata identifiers - + XCTAssertEqual("0.0.0-beta.-42+42-42.42" as Version, Version(0, 0, 0, prereleaseIdentifiers: ["beta", "-42"], buildMetadataIdentifiers: ["42-42", "42"])) - + // MARK: Well-formed version core, well-formed pre-release identifiers, malformed build metadata identifiers - + XCTAssertEqual("514229.832040.1346269-beta1+ " as Version, Version(0, 0, 0)) - + // MARK: Well-formed version core, malformed pre-release identifiers, well-formed build metadata identifiers - + XCTAssertEqual("832040.1346269.2178309-beta 1+-" as Version, Version(0, 0, 0)) - + // MARK: Well-formed version core, malformed pre-release identifiers, malformed build metadata identifiers - + XCTAssertEqual("1346269.2178309.3524578-beta 1++" as Version, Version(0, 0, 0)) - + // MARK: malformed version core, well-formed pre-release identifiers, well-formed build metadata identifiers - + XCTAssertEqual(" 832040.1346269.3524578-beta1+abc" as Version, Version(0, 0, 0)) - + // MARK: malformed version core, well-formed pre-release identifiers, malformed build metadata identifiers - + XCTAssertEqual("1346269.3524578.5702887-beta1+😀" as Version, Version(0, 0, 0)) - + // MARK: malformed version core, malformed pre-release identifiers, well-formed build metadata identifiers - + XCTAssertEqual("3524578.5702887.9227465-beta!@#$%^&*1+asdfghjkl123456789" as Version, Version(0, 0, 0)) - + // MARK: malformed version core, malformed pre-release identifiers, malformed build metadata identifiers - + XCTAssertEqual("5702887.9227465-bètá1+±" as Version, Version(0, 0, 0)) - + } - + // A semantic version string is always longer than 1 character, so the only way to test these 2 initializers is by calling them directly. - + func testExpressingVersionByExtendedGraphemeClusterLiteral() { XCTAssertEqual(Version(extendedGraphemeClusterLiteral: "版⃣"), Version(0, 0, 0)) } - + func testExpressingVersionByUnicodeScalarLiteral() { XCTAssertEqual(Version(unicodeScalarLiteral: "a"), Version(0, 0, 0)) } - -} +} diff --git a/Tests/PackageFingerprintTests/FilePackageFingerprintStorageTests.swift b/Tests/PackageFingerprintTests/FilePackageFingerprintStorageTests.swift index ce9d6a034f1..eb2872023ba 100644 --- a/Tests/PackageFingerprintTests/FilePackageFingerprintStorageTests.swift +++ b/Tests/PackageFingerprintTests/FilePackageFingerprintStorageTests.swift @@ -116,12 +116,14 @@ final class FilePackageFingerprintStorageTests: XCTestCase { ) // No fingerprints found for the content type - await XCTAssertAsyncThrowsError(try storage.get( - package: package, - version: Version("1.0.0"), - kind: .registry, - contentType: .manifest(.none) - )) { error in + await XCTAssertAsyncThrowsError( + try storage.get( + package: package, + version: Version("1.0.0"), + kind: .registry, + contentType: .manifest(.none) + ) + ) { error in guard case PackageFingerprintStorageError.notFound = error else { return XCTFail("Expected PackageFingerprintStorageError.notFound, got \(error)") } @@ -158,15 +160,17 @@ final class FilePackageFingerprintStorageTests: XCTestCase { ) // Writing for the same version and kind and content type but different checksum should fail - await XCTAssertAsyncThrowsError(try storage.put( - package: package, - version: Version("1.0.0"), - fingerprint: .init( - origin: .registry(registryURL), - value: "checksum-1.0.0-1", - contentType: .sourceCode + await XCTAssertAsyncThrowsError( + try storage.put( + package: package, + version: Version("1.0.0"), + fingerprint: .init( + origin: .registry(registryURL), + value: "checksum-1.0.0-1", + contentType: .sourceCode + ) ) - )) { error in + ) { error in guard case PackageFingerprintStorageError.conflict = error else { return XCTFail("Expected PackageFingerprintStorageError.conflict, got \(error)") } @@ -260,15 +264,17 @@ final class FilePackageFingerprintStorageTests: XCTestCase { ) // This should fail because fingerprint for 1.0.0 already exists and it's different - await XCTAssertAsyncThrowsError(try storage.put( - package: fooRef, - version: Version("1.0.0"), - fingerprint: .init( - origin: .sourceControl(fooURL), - value: "abcde-foo-foo", - contentType: .sourceCode + await XCTAssertAsyncThrowsError( + try storage.put( + package: fooRef, + version: Version("1.0.0"), + fingerprint: .init( + origin: .sourceControl(fooURL), + value: "abcde-foo-foo", + contentType: .sourceCode + ) ) - )) { error in + ) { error in guard case PackageFingerprintStorageError.conflict = error else { return XCTFail("Expected PackageFingerprintStorageError.conflict, got \(error)") } @@ -292,23 +298,23 @@ final class FilePackageFingerprintStorageTests: XCTestCase { let package = PackageIdentity.plain("mona.LinkedList") let fingerprintsPath = directoryPath.appending(package.fingerprintsFilename) let v1Fingerprints = """ - { - "versionFingerprints" : { - "1.0.3" : { - "sourceControl" : { - "fingerprint" : "e394bf350e38cb100b6bc4172834770ede1b7232", - "origin" : "\(sourceControlURL)" - } - }, - "1.2.2" : { - "sourceControl" : { - "fingerprint" : "fee6933f37fde9a5e12a1e4aeaa93fe60116ff2a", - "origin" : "\(sourceControlURL)" + { + "versionFingerprints" : { + "1.0.3" : { + "sourceControl" : { + "fingerprint" : "e394bf350e38cb100b6bc4172834770ede1b7232", + "origin" : "\(sourceControlURL)" + } + }, + "1.2.2" : { + "sourceControl" : { + "fingerprint" : "fee6933f37fde9a5e12a1e4aeaa93fe60116ff2a", + "origin" : "\(sourceControlURL)" + } + } } } - } - } - """ + """ // Write v1 fingerprints file try mockFileSystem.writeFileContents(fingerprintsPath, string: v1Fingerprints) diff --git a/Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift b/Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift index a29c688f3e1..04c06014452 100644 --- a/Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift +++ b/Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift @@ -30,33 +30,33 @@ import struct TSCUtility.Version import class TSCTestSupport.XCTestCasePerf private let v1: Version = "1.0.0" -private let v1Range: VersionSetSpecifier = .range("1.0.0" ..< "2.0.0") +private let v1Range: VersionSetSpecifier = .range("1.0.0"..<"2.0.0") class DependencyResolverRealWorldPerfTests: XCTestCasePerf { func testKituraPubGrub_X100() async throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif try await runPackageTestPubGrub(name: "kitura.json", N: 100) } func testZewoPubGrub_X100() async throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif try await runPackageTestPubGrub(name: "ZewoHTTPServer.json", N: 100) } func testPerfectPubGrub_X100() async throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif try await runPackageTestPubGrub(name: "PerfectHTTPServer.json", N: 100) } func testSourceKittenPubGrub_X100() async throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif try await runPackageTestPubGrub(name: "SourceKitten.json", N: 100) } @@ -67,7 +67,7 @@ class DependencyResolverRealWorldPerfTests: XCTestCasePerf { self.startMeasuring() - for _ in 0 ..< N { + for _ in 0.. Manifest in @@ -145,7 +147,7 @@ final class PackageGraphPerfTests: XCTestCasePerf { path: "/PackageA", toolsVersion: .v5_7, dependencies: try packageNumberSequence.map({ .fileSystem(path: try .init(validating: "/Package\($0)")) }), - targets: [try .init(name: "TargetA", dependencies: ["Target1"]) ] + targets: [try .init(name: "TargetA", dependencies: ["Target1"])] ) let observability = ObservabilitySystem.makeForTesting() @@ -172,7 +174,7 @@ final class PackageGraphPerfTests: XCTestCasePerf { var resolvedTarget = ResolvedModule.mock(packageIdentity: "pkg", name: "t0") for i in 1..<1000 { resolvedTarget = ResolvedModule.mock(packageIdentity: "pkg", name: "t\(i)", deps: resolvedTarget) - } + } let N = 10 measure { diff --git a/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift b/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift index 1a46d2509b8..615d30b198c 100644 --- a/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift +++ b/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift @@ -10,12 +10,9 @@ // //===----------------------------------------------------------------------===// -@testable -@_spi(SwiftPMInternal) -import _InternalTestSupport +@testable @_spi(SwiftPMInternal) import _InternalTestSupport -@testable -import PackageGraph +@testable import PackageGraph import PackageModel import XCTest diff --git a/Tests/PackageGraphTests/DependencyResolverTests.swift b/Tests/PackageGraphTests/DependencyResolverTests.swift index 6f467772cec..1e4eecf2646 100644 --- a/Tests/PackageGraphTests/DependencyResolverTests.swift +++ b/Tests/PackageGraphTests/DependencyResolverTests.swift @@ -31,16 +31,16 @@ private typealias MockPackageConstraint = PackageContainerConstraint private let v1: Version = "1.0.0" private let v1_1: Version = "1.1.0" private let v2: Version = "2.0.0" -private let v0_0_0Range: VersionSetSpecifier = .range("0.0.0" ..< "0.0.1") -private let v1Range: VersionSetSpecifier = .range("1.0.0" ..< "2.0.0") -private let v1to3Range: VersionSetSpecifier = .range("1.0.0" ..< "3.0.0") -private let v2Range: VersionSetSpecifier = .range("2.0.0" ..< "3.0.0") -private let v1_to_3Range: VersionSetSpecifier = .range("1.0.0" ..< "3.0.0") -private let v2_to_4Range: VersionSetSpecifier = .range("2.0.0" ..< "4.0.0") -private let v1_0Range: VersionSetSpecifier = .range("1.0.0" ..< "1.1.0") -private let v1_1Range: VersionSetSpecifier = .range("1.1.0" ..< "1.2.0") -private let v1_1_0Range: VersionSetSpecifier = .range("1.1.0" ..< "1.1.1") -private let v2_0_0Range: VersionSetSpecifier = .range("2.0.0" ..< "2.0.1") +private let v0_0_0Range: VersionSetSpecifier = .range("0.0.0"..<"0.0.1") +private let v1Range: VersionSetSpecifier = .range("1.0.0"..<"2.0.0") +private let v1to3Range: VersionSetSpecifier = .range("1.0.0"..<"3.0.0") +private let v2Range: VersionSetSpecifier = .range("2.0.0"..<"3.0.0") +private let v1_to_3Range: VersionSetSpecifier = .range("1.0.0"..<"3.0.0") +private let v2_to_4Range: VersionSetSpecifier = .range("2.0.0"..<"4.0.0") +private let v1_0Range: VersionSetSpecifier = .range("1.0.0"..<"1.1.0") +private let v1_1Range: VersionSetSpecifier = .range("1.1.0"..<"1.2.0") +private let v1_1_0Range: VersionSetSpecifier = .range("1.1.0"..<"1.1.1") +private let v2_0_0Range: VersionSetSpecifier = .range("2.0.0"..<"2.0.1") class DependencyResolverTests: XCTestCase { func testVersionSetSpecifier() { @@ -54,7 +54,7 @@ class DependencyResolverTests: XCTestCase { XCTAssert(v1Range.intersection(v2Range) == .empty) XCTAssert(v1Range.intersection(v2_0_0Range) == .empty) XCTAssert(v1Range.intersection(v1_1Range) == v1_1Range) - XCTAssert(v1_to_3Range.intersection(v2_to_4Range) == .range("2.0.0" ..< "3.0.0")) + XCTAssert(v1_to_3Range.intersection(v2_to_4Range) == .range("2.0.0"..<"3.0.0")) XCTAssert(v1Range.intersection(.any) == v1Range) XCTAssert(VersionSetSpecifier.empty.intersection(.any) == .empty) XCTAssert(VersionSetSpecifier.any.intersection(.any) == .any) diff --git a/Tests/PackageGraphTests/ModulesGraphTests+Traits.swift b/Tests/PackageGraphTests/ModulesGraphTests+Traits.swift index 4212ae76612..13a728f6135 100644 --- a/Tests/PackageGraphTests/ModulesGraphTests+Traits.swift +++ b/Tests/PackageGraphTests/ModulesGraphTests+Traits.swift @@ -16,8 +16,7 @@ import TSCUtility import Testing import _InternalTestSupport -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -@testable import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) @testable import PackageGraph extension ModulesGraphTests { @Test @@ -38,13 +37,13 @@ extension ModulesGraphTests { targets: [ TargetDescription( name: "Foo" - ), + ) ], traits: [ .init(name: "default", enabledTraits: ["Trait1"]), "Trait1", ] - ), + ) ], observabilityScope: observability.topScope, enabledTraitsMap: [ @@ -79,7 +78,7 @@ extension ModulesGraphTests { targets: [ TargetDescription( name: "Foo" - ), + ) ], traits: [ .init(name: "default", enabledTraits: ["Trait1"]), @@ -89,7 +88,7 @@ extension ModulesGraphTests { .init(name: "Trait4", enabledTraits: ["Trait5"]), "Trait5", ] - ), + ) ], observabilityScope: observability.topScope, enabledTraitsMap: [ @@ -126,15 +125,15 @@ extension ModulesGraphTests { path: "/Package2", requirement: .upToNextMajor(from: "1.0.0"), traits: ["Package2Trait1"] - ), + ) ], targets: [ TargetDescription( name: "Package1Target1", dependencies: [ - .product(name: "Package2Target1", package: "Package2"), + .product(name: "Package2Target1", package: "Package2") ] - ), + ) ], traits: [ .init(name: "default", enabledTraits: ["Package1Trait1"]), @@ -150,22 +149,22 @@ extension ModulesGraphTests { name: "Package2Target1", type: .library(.automatic), targets: ["Package2Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package2Target1" - ), + ) ], traits: [ - "Package2Trait1", + "Package2Trait1" ] ), ], observabilityScope: observability.topScope, enabledTraitsMap: [ "Package1": ["Package1Trait1"], - "Package2": ["Package2Trait1"] + "Package2": ["Package2Trait1"], ] ) @@ -200,15 +199,15 @@ extension ModulesGraphTests { path: "/Package2", requirement: .upToNextMajor(from: "1.0.0"), traits: .init([.init(name: "Package2Trait1", condition: .init(traits: ["Package1Trait1"]))]) - ), + ) ], targets: [ TargetDescription( name: "Package1Target1", dependencies: [ - .product(name: "Package2Target1", package: "Package2"), + .product(name: "Package2Target1", package: "Package2") ] - ), + ) ], traits: [ .init(name: "default", enabledTraits: ["Package1Trait1"]), @@ -224,15 +223,15 @@ extension ModulesGraphTests { name: "Package2Target1", type: .library(.automatic), targets: ["Package2Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package2Target1" - ), + ) ], traits: [ - "Package2Trait1", + "Package2Trait1" ] ), ] @@ -243,7 +242,7 @@ extension ModulesGraphTests { observabilityScope: observability.topScope, enabledTraitsMap: [ "Package1": ["Package1Trait1"], - "Package2": ["Package2Trait1"] + "Package2": ["Package2Trait1"], ] ) @@ -264,7 +263,7 @@ extension ModulesGraphTests { func traits_whenComplex() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Package1/Sources/Package1Target1/source.swift", + "/Package1/Sources/Package1Target1/source.swift", "/Package2/Sources/Package2Target1/source.swift", "/Package3/Sources/Package3Target1/source.swift", "/Package4/Sources/Package4Target1/source.swift", @@ -309,9 +308,9 @@ extension ModulesGraphTests { tool: .swift, kind: .define("TEST_DEFINE"), condition: .init(traits: ["Package1Trait1"]) - ), + ) ] - ), + ) ], traits: [ .init(name: "default", enabledTraits: ["Package1Trait1", "Package1Trait2"]), @@ -328,25 +327,25 @@ extension ModulesGraphTests { path: "/Package3", requirement: .upToNextMajor(from: "1.0.0"), traits: .init([.init(name: "Package3Trait1", condition: .init(traits: ["Package2Trait1"]))]) - ), + ) ], products: [ .init( name: "Package2Target1", type: .library(.automatic), targets: ["Package2Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package2Target1", dependencies: [ - .product(name: "Package3Target1", package: "Package3"), + .product(name: "Package3Target1", package: "Package3") ] - ), + ) ], traits: [ - "Package2Trait1", + "Package2Trait1" ] ), Manifest.createFileSystemManifest( @@ -358,25 +357,25 @@ extension ModulesGraphTests { path: "/Package4", requirement: .upToNextMajor(from: "1.0.0"), traits: .init([.init(name: "Package4Trait1", condition: .init(traits: ["Package3Trait1"]))]) - ), + ) ], products: [ .init( name: "Package3Target1", type: .library(.automatic), targets: ["Package3Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package3Target1", dependencies: [ - .product(name: "Package4Target1", package: "Package4"), + .product(name: "Package4Target1", package: "Package4") ] - ), + ) ], traits: [ - "Package3Trait1", + "Package3Trait1" ] ), Manifest.createFileSystemManifest( @@ -388,12 +387,12 @@ extension ModulesGraphTests { name: "Package4Target1", type: .library(.automatic), targets: ["Package4Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package4Target1" - ), + ) ], traits: [ "Package4Trait1", @@ -409,12 +408,12 @@ extension ModulesGraphTests { name: "Package5Target1", type: .library(.automatic), targets: ["Package5Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package5Target1" - ), + ) ] ), ] @@ -427,7 +426,7 @@ extension ModulesGraphTests { "Package1": ["Package1Trait1", "Package1Trait2"], "Package2": ["Package2Trait1"], "Package3": ["Package3Trait1"], - "Package4": ["Package4Trait1", "Package4Trait2"] + "Package4": ["Package4Trait1", "Package4Trait2"], ] ) @@ -517,7 +516,7 @@ extension ModulesGraphTests { condition: .init(traits: ["Package1Trait3"]) ), ] - ), + ) ], traits: [ .init(name: "default", enabledTraits: ["Package1Trait3"]), @@ -536,25 +535,25 @@ extension ModulesGraphTests { path: "/Package3", requirement: .upToNextMajor(from: "1.0.0"), traits: .init([.init(name: "Package3Trait1", condition: .init(traits: ["Package2Trait1"]))]) - ), + ) ], products: [ .init( name: "Package2Target1", type: .library(.automatic), targets: ["Package2Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package2Target1", dependencies: [ - .product(name: "Package3Target1", package: "Package3"), + .product(name: "Package3Target1", package: "Package3") ] - ), + ) ], traits: [ - "Package2Trait1", + "Package2Trait1" ], pruneDependencies: true ), @@ -567,25 +566,25 @@ extension ModulesGraphTests { path: "/Package4", requirement: .upToNextMajor(from: "1.0.0"), traits: .init([.init(name: "Package4Trait1", condition: .init(traits: ["Package3Trait1"]))]) - ), + ) ], products: [ .init( name: "Package3Target1", type: .library(.automatic), targets: ["Package3Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package3Target1", dependencies: [ - .product(name: "Package4Target1", package: "Package4"), + .product(name: "Package4Target1", package: "Package4") ] - ), + ) ], traits: [ - "Package3Trait1", + "Package3Trait1" ], pruneDependencies: true ), @@ -598,12 +597,12 @@ extension ModulesGraphTests { name: "Package4Target1", type: .library(.automatic), targets: ["Package4Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package4Target1" - ), + ) ], traits: [ "Package4Trait1", @@ -620,12 +619,12 @@ extension ModulesGraphTests { name: "Package5Target1", type: .library(.automatic), targets: ["Package5Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package5Target1" - ), + ) ], pruneDependencies: true ), @@ -639,7 +638,7 @@ extension ModulesGraphTests { "Package1": ["Package1Trait3"], "Package2": [], "Package3": [], - "Package4": ["Package4Trait2"] + "Package4": ["Package4Trait2"], ] ) @@ -728,7 +727,7 @@ extension ModulesGraphTests { condition: .init(traits: ["Package1Trait3"]) ), ] - ), + ) ], traits: [ .init(name: "default", enabledTraits: ["Package1Trait3"]), @@ -747,25 +746,25 @@ extension ModulesGraphTests { path: "/Package3", requirement: .upToNextMajor(from: "1.0.0"), traits: .init([.init(name: "Package3Trait1", condition: .init(traits: ["Package2Trait1"]))]) - ), + ) ], products: [ .init( name: "Package2Target1", type: .library(.automatic), targets: ["Package2Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package2Target1", dependencies: [ - .product(name: "Package3Target1", package: "Package3"), + .product(name: "Package3Target1", package: "Package3") ] - ), + ) ], traits: [ - "Package2Trait1", + "Package2Trait1" ], pruneDependencies: true ), @@ -778,25 +777,25 @@ extension ModulesGraphTests { path: "/Package4", requirement: .upToNextMajor(from: "1.0.0"), traits: .init([.init(name: "Package4Trait1", condition: .init(traits: ["Package3Trait1"]))]) - ), + ) ], products: [ .init( name: "Package3Target1", type: .library(.automatic), targets: ["Package3Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package3Target1", dependencies: [ - .product(name: "Package4Target1", package: "Package4"), + .product(name: "Package4Target1", package: "Package4") ] - ), + ) ], traits: [ - "Package3Trait1", + "Package3Trait1" ], pruneDependencies: true ), @@ -809,12 +808,12 @@ extension ModulesGraphTests { name: "Package4Target1", type: .library(.automatic), targets: ["Package4Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package4Target1" - ), + ) ], traits: [ "Package4Trait1", @@ -831,12 +830,12 @@ extension ModulesGraphTests { name: "Package5Target1", type: .library(.automatic), targets: ["Package5Target1"] - ), + ) ], targets: [ TargetDescription( name: "Package5Target1" - ), + ) ], pruneDependencies: true ), @@ -850,7 +849,7 @@ extension ModulesGraphTests { "Package1": ["Package1Trait3"], "Package2": [], "Package3": [], - "Package4": ["Package4Trait2"] + "Package4": ["Package4Trait2"], ] ) @@ -904,7 +903,7 @@ extension ModulesGraphTests { .localSourceControl( path: "/Juice", requirement: .upToNextMajor(from: "1.0.0") - ) + ), ], targets: [ TargetDescription( @@ -919,9 +918,9 @@ extension ModulesGraphTests { name: "AppleJuice", package: "Juice", condition: .init(traits: ["EnableAppleJuiceDep"]) - ) + ), ], - ), + ) ], traits: [ .init(name: "default", enabledTraits: ["EnableCoffeeDep"]), @@ -938,12 +937,12 @@ extension ModulesGraphTests { name: "Coffee", type: .library(.automatic), targets: ["CoffeeTarget"] - ), + ) ], targets: [ TargetDescription( name: "CoffeeTarget", - ), + ) ], ), Manifest.createFileSystemManifest( @@ -955,14 +954,14 @@ extension ModulesGraphTests { name: "AppleJuice", type: .library(.automatic), targets: ["AppleJuiceTarget"] - ), + ) ], targets: [ TargetDescription( name: "AppleJuiceTarget", - ), + ) ], - ) + ), ] // Test graph with default trait configuration @@ -1000,7 +999,7 @@ extension ModulesGraphTests { observabilityScope: observability.topScope, traitConfiguration: .disableAllTraits, enabledTraitsMap: [ - "Lunch": [], + "Lunch": [] ] ) #expect(observability.diagnostics.count == 0) @@ -1028,7 +1027,7 @@ extension ModulesGraphTests { observabilityScope: observability.topScope, traitConfiguration: .enabledTraits(["EnableAppleJuiceDep"]), enabledTraitsMap: [ - "Lunch": ["EnableAppleJuiceDep"], + "Lunch": ["EnableAppleJuiceDep"] ] ) #expect(observability.diagnostics.count == 0) diff --git a/Tests/PackageGraphTests/ModulesGraphTests.swift b/Tests/PackageGraphTests/ModulesGraphTests.swift index 1089a3ab30b..12f5909890b 100644 --- a/Tests/PackageGraphTests/ModulesGraphTests.swift +++ b/Tests/PackageGraphTests/ModulesGraphTests.swift @@ -15,8 +15,7 @@ import Basics import PackageLoading import TSCUtility -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -@testable import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) @testable import PackageGraph import _InternalTestSupport import PackageModel @@ -45,7 +44,7 @@ struct ModulesGraphTests { binaryArtifacts: [:], ) - #expect(throws: StringError("Root package does not exist.")) { // Index out of range + #expect(throws: StringError("Root package does not exist.")) { // Index out of range let _ = try moduleGraph.getReplProductName() } } @@ -119,7 +118,7 @@ struct ModulesGraphTests { try withKnownIssue { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/source.swift", + "/Foo/Sources/Foo/source.swift", "/Foo/Sources/Foo/source.swift", "/Foo/Sources/FooDep/source.swift", "/Foo/Tests/FooTests/source.swift", @@ -136,7 +135,7 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ], targets: [ TargetDescription(name: "Foo", dependencies: ["FooDep"]), @@ -147,20 +146,20 @@ struct ModulesGraphTests { displayName: "Bar", path: "/Bar", dependencies: [ - .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar", dependencies: ["Foo"], path: "./"), + TargetDescription(name: "Bar", dependencies: ["Foo"], path: "./") ] ), Manifest.createRootManifest( displayName: "Baz", path: "/Baz", dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription(name: "Baz", dependencies: ["Bar"]), @@ -198,7 +197,7 @@ struct ModulesGraphTests { func productDependencies() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/source.swift", + "/Foo/Sources/Foo/source.swift", "/Bar/Source/Bar/source.swift", "/Bar/Source/CBar/module.modulemap" ) @@ -211,10 +210,10 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar", "CBar"]), + TargetDescription(name: "Foo", dependencies: ["Bar", "CBar"]) ] ), Manifest.createFileSystemManifest( @@ -259,36 +258,36 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar"]), + TargetDescription(name: "Foo", dependencies: ["Bar"]) ] ), Manifest.createFileSystemManifest( displayName: "Bar", path: "/Bar", dependencies: [ - .localSourceControl(path: "/Baz", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Baz", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar", dependencies: ["Baz"]), + TargetDescription(name: "Bar", dependencies: ["Baz"]) ] ), Manifest.createFileSystemManifest( displayName: "Baz", path: "/Baz", dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Baz", type: .library(.automatic), targets: ["Baz"]), + ProductDescription(name: "Baz", type: .library(.automatic), targets: ["Baz"]) ], targets: [ - TargetDescription(name: "Baz", dependencies: ["Bar"]), + TargetDescription(name: "Baz", dependencies: ["Bar"]) ] ), ], @@ -322,7 +321,7 @@ struct ModulesGraphTests { TargetDescription(name: "Foo", dependencies: ["Bar"]), TargetDescription(name: "Bar", dependencies: ["Foo"]), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -353,20 +352,20 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_10, dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar"]), + TargetDescription(name: "Foo", dependencies: ["Bar"]) ] ), Manifest.createFileSystemManifest( displayName: "Bar", path: "/Bar", dependencies: [ - .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), @@ -408,39 +407,39 @@ struct ModulesGraphTests { path: "/A", toolsVersion: rootToolsVersion, dependencies: [ - .localSourceControl(path: "/B", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/B", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]), + ProductDescription(name: "A", type: .library(.automatic), targets: ["A"]) ], targets: [ - TargetDescription(name: "A", dependencies: ["B"]), + TargetDescription(name: "A", dependencies: ["B"]) ] ), Manifest.createFileSystemManifest( displayName: "B", path: "/B", dependencies: [ - .localSourceControl(path: "/C", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/C", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]), + ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]) ], targets: [ - TargetDescription(name: "B"), + TargetDescription(name: "B") ] ), Manifest.createFileSystemManifest( displayName: "C", path: "/C", dependencies: [ - .localSourceControl(path: "/A", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/A", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]), + ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]) ], targets: [ - TargetDescription(name: "C"), + TargetDescription(name: "C") ] ), ], @@ -477,20 +476,20 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v6_0, dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar"]), + TargetDescription(name: "Foo", dependencies: ["Bar"]) ] ), Manifest.createFileSystemManifest( displayName: "Bar", path: "/Bar", dependencies: [ - .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), @@ -530,13 +529,13 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v6_0, products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["FooTest"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["FooTest"]) ], targets: [ TargetDescription(name: "Foo", dependencies: ["FooTest"]), TargetDescription(name: "FooTest", type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -570,7 +569,7 @@ struct ModulesGraphTests { TargetDescription(name: "Foo", dependencies: ["FooTest"], type: .executable), TargetDescription(name: "FooTest", type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -609,7 +608,7 @@ struct ModulesGraphTests { ), TargetDescription(name: "FooTest", type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -647,7 +646,7 @@ struct ModulesGraphTests { ), TargetDescription(name: "FooTest", type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -660,7 +659,6 @@ struct ModulesGraphTests { } } - @Test func validDependencyOnTestTarget() throws { let fs = InMemoryFileSystem( @@ -678,13 +676,12 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", toolsVersion: .v6_0, - products: [ - ], + products: [], targets: [ TargetDescription(name: "Foo", dependencies: ["FooTest"], type: .test), TargetDescription(name: "FooTest", type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -712,7 +709,7 @@ struct ModulesGraphTests { displayName: "Bar", path: "/Bar", dependencies: [ - .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription(name: "Bar", dependencies: ["Foo"]), @@ -723,7 +720,7 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ], targets: [ TargetDescription(name: "Foo", dependencies: []), @@ -780,7 +777,7 @@ struct ModulesGraphTests { packageAccess: true ), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -813,7 +810,7 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription(name: "Foo"), @@ -858,30 +855,30 @@ struct ModulesGraphTests { displayName: "Fourth", path: "/Fourth", products: [ - ProductDescription(name: "Fourth", type: .library(.automatic), targets: ["First"]), + ProductDescription(name: "Fourth", type: .library(.automatic), targets: ["First"]) ], targets: [ - TargetDescription(name: "First"), + TargetDescription(name: "First") ] ), Manifest.createFileSystemManifest( displayName: "Third", path: "/Third", products: [ - ProductDescription(name: "Third", type: .library(.automatic), targets: ["First"]), + ProductDescription(name: "Third", type: .library(.automatic), targets: ["First"]) ], targets: [ - TargetDescription(name: "First"), + TargetDescription(name: "First") ] ), Manifest.createFileSystemManifest( displayName: "Second", path: "/Second", products: [ - ProductDescription(name: "Second", type: .library(.automatic), targets: ["First"]), + ProductDescription(name: "Second", type: .library(.automatic), targets: ["First"]) ], targets: [ - TargetDescription(name: "First"), + TargetDescription(name: "First") ] ), Manifest.createRootManifest( @@ -893,7 +890,7 @@ struct ModulesGraphTests { .localSourceControl(path: "/Fourth", requirement: .upToNextMajor(from: "1.0.0")), ], targets: [ - TargetDescription(name: "First", dependencies: ["Second", "Third", "Fourth"]), + TargetDescription(name: "First", dependencies: ["Second", "Third", "Fourth"]) ] ), ], @@ -930,7 +927,7 @@ struct ModulesGraphTests { displayName: "Fourth", path: "/Fourth", products: [ - ProductDescription(name: "Fourth", type: .library(.automatic), targets: ["Fourth", "Bar"]), + ProductDescription(name: "Fourth", type: .library(.automatic), targets: ["Fourth", "Bar"]) ], targets: [ TargetDescription(name: "Fourth"), @@ -941,7 +938,7 @@ struct ModulesGraphTests { displayName: "Third", path: "/Third", products: [ - ProductDescription(name: "Third", type: .library(.automatic), targets: ["Third", "Bar"]), + ProductDescription(name: "Third", type: .library(.automatic), targets: ["Third", "Bar"]) ], targets: [ TargetDescription(name: "Third"), @@ -952,7 +949,7 @@ struct ModulesGraphTests { displayName: "Second", path: "/Second", products: [ - ProductDescription(name: "Second", type: .library(.automatic), targets: ["Second", "Foo"]), + ProductDescription(name: "Second", type: .library(.automatic), targets: ["Second", "Foo"]) ], targets: [ TargetDescription(name: "Second"), @@ -968,7 +965,7 @@ struct ModulesGraphTests { .localSourceControl(path: "/Fourth", requirement: .upToNextMajor(from: "1.0.0")), ], products: [ - ProductDescription(name: "First", type: .library(.automatic), targets: ["First", "Foo"]), + ProductDescription(name: "First", type: .library(.automatic), targets: ["First", "Foo"]) ], targets: [ TargetDescription(name: "First"), @@ -1010,7 +1007,7 @@ struct ModulesGraphTests { displayName: "Fourth", path: "/Fourth", products: [ - ProductDescription(name: "Fourth", type: .library(.automatic), targets: ["Fourth", "First"]), + ProductDescription(name: "Fourth", type: .library(.automatic), targets: ["Fourth", "First"]) ], targets: [ TargetDescription(name: "Fourth"), @@ -1021,39 +1018,39 @@ struct ModulesGraphTests { displayName: "Third", path: "/Third", dependencies: [ - .localSourceControl(path: "/Fourth", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Fourth", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Third", type: .library(.automatic), targets: ["Third"]), + ProductDescription(name: "Third", type: .library(.automatic), targets: ["Third"]) ], targets: [ - TargetDescription(name: "Third", dependencies: ["Fourth"]), + TargetDescription(name: "Third", dependencies: ["Fourth"]) ] ), Manifest.createFileSystemManifest( displayName: "Second", path: "/Second", dependencies: [ - .localSourceControl(path: "/Third", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Third", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "Second", type: .library(.automatic), targets: ["Second"]), + ProductDescription(name: "Second", type: .library(.automatic), targets: ["Second"]) ], targets: [ - TargetDescription(name: "Second", dependencies: ["Third"]), + TargetDescription(name: "Second", dependencies: ["Third"]) ] ), Manifest.createRootManifest( displayName: "First", path: "/First", dependencies: [ - .localSourceControl(path: "/Second", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Second", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "First", type: .library(.automatic), targets: ["First"]), + ProductDescription(name: "First", type: .library(.automatic), targets: ["First"]) ], targets: [ - TargetDescription(name: "First", dependencies: ["Second"]), + TargetDescription(name: "First", dependencies: ["Second"]) ] ), ], @@ -1086,10 +1083,10 @@ struct ModulesGraphTests { displayName: "First", path: "/First", dependencies: [ - .localSourceControl(path: "/Second", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Second", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "First", type: .library(.automatic), targets: ["Foo", "Bar"]), + ProductDescription(name: "First", type: .library(.automatic), targets: ["Foo", "Bar"]) ], targets: [ TargetDescription(name: "Foo"), @@ -1100,7 +1097,7 @@ struct ModulesGraphTests { displayName: "Second", path: "/Second", products: [ - ProductDescription(name: "Second", type: .library(.automatic), targets: ["Foo", "Bar"]), + ProductDescription(name: "Second", type: .library(.automatic), targets: ["Foo", "Bar"]) ], targets: [ TargetDescription(name: "Foo"), @@ -1143,14 +1140,14 @@ struct ModulesGraphTests { displayName: "First", path: "/First", dependencies: [ - .localSourceControl(path: "/Second", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Second", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ ProductDescription( name: "First", type: .library(.automatic), targets: ["Foo", "Bar", "Baz", "Qux", "Quux"] - ), + ) ], targets: [ TargetDescription(name: "Foo"), @@ -1168,7 +1165,7 @@ struct ModulesGraphTests { name: "Second", type: .library(.automatic), targets: ["Foo", "Bar", "Baz", "Qux", "Quux"] - ), + ) ], targets: [ TargetDescription(name: "Foo"), @@ -1210,10 +1207,10 @@ struct ModulesGraphTests { displayName: "First", path: "/First", dependencies: [ - .registry(identity: "test.second", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "test.second", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "First", type: .library(.automatic), targets: ["Foo", "Bar"]), + ProductDescription(name: "First", type: .library(.automatic), targets: ["Foo", "Bar"]) ], targets: [ TargetDescription(name: "Foo"), @@ -1225,7 +1222,7 @@ struct ModulesGraphTests { identity: .plain("test.second"), path: "/Second", products: [ - ProductDescription(name: "Second", type: .library(.automatic), targets: ["Foo", "Bar"]), + ProductDescription(name: "Second", type: .library(.automatic), targets: ["Foo", "Bar"]) ], targets: [ TargetDescription(name: "Foo"), @@ -1264,20 +1261,20 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar"]), + TargetDescription(name: "Foo", dependencies: ["Bar"]) ] ), Manifest.createFileSystemManifest( displayName: "Bar", path: .init(validating: Bar.pathString), products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ], @@ -1311,12 +1308,12 @@ struct ModulesGraphTests { displayName: "Bar", path: "/Bar", products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] - ), + ) ], observabilityScope: observability.topScope ) @@ -1343,9 +1340,9 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", targets: [ - TargetDescription(name: "FooTarget", dependencies: ["Barx"]), + TargetDescription(name: "FooTarget", dependencies: ["Barx"]) ] - ), + ) ], observabilityScope: observability.topScope ) @@ -1377,7 +1374,7 @@ struct ModulesGraphTests { TargetDescription(name: "Rail", dependencies: ["Spoke"]), TargetDescription(name: "Spike"), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -1406,10 +1403,10 @@ struct ModulesGraphTests { displayName: "weather", path: "/weather", products: [ - ProductDescription(name: "Rain", type: .library(.automatic), targets: ["Rain"]), + ProductDescription(name: "Rain", type: .library(.automatic), targets: ["Rain"]) ], targets: [ - TargetDescription(name: "Rain"), + TargetDescription(name: "Rain") ] ), Manifest.createRootManifest( @@ -1417,7 +1414,7 @@ struct ModulesGraphTests { path: "/forecast", dependencies: [.fileSystem(path: "/weather")], targets: [ - TargetDescription(name: "Forecast", dependencies: ["Rail"]), + TargetDescription(name: "Forecast", dependencies: ["Rail"]) ] ), ], @@ -1450,7 +1447,7 @@ struct ModulesGraphTests { path: "/flavors", products: [ProductDescription(name: "Bitter", type: .library(.automatic), targets: ["Bitter"])], targets: [ - TargetDescription(name: "Bitter"), + TargetDescription(name: "Bitter") ] ), Manifest.createFileSystemManifest( @@ -1458,7 +1455,7 @@ struct ModulesGraphTests { path: "/farm", products: [ProductDescription(name: "Butter", type: .library(.automatic), targets: ["Butter"])], targets: [ - TargetDescription(name: "Butter"), + TargetDescription(name: "Butter") ] ), Manifest.createRootManifest( @@ -1466,10 +1463,13 @@ struct ModulesGraphTests { path: "/grocery", dependencies: [.fileSystem(path: "/farm"), .fileSystem(path: "/flavors")], targets: [ - TargetDescription(name: "Grocery", dependencies: [ - .product(name: "Biter", package: "farm"), - .product(name: "Bitter", package: "flavors"), - ]), + TargetDescription( + name: "Grocery", + dependencies: [ + .product(name: "Biter", package: "farm"), + .product(name: "Bitter", package: "flavors"), + ] + ) ] ), ], @@ -1502,11 +1502,13 @@ struct ModulesGraphTests { Manifest.createFileSystemManifest( displayName: "sandwich", path: "/sandwich", - products: [ProductDescription( - name: "Sandwich", - type: .library(.automatic), - targets: ["Sandwich"] - )], + products: [ + ProductDescription( + name: "Sandwich", + type: .library(.automatic), + targets: ["Sandwich"] + ) + ], targets: [ TargetDescription(name: "Sandwich", dependencies: ["Bread"]), TargetDescription(name: "Bread"), @@ -1519,7 +1521,7 @@ struct ModulesGraphTests { // but there's a target with the same name. dependencies: [.fileSystem(path: "/sandwich")], targets: [ - TargetDescription(name: "Lunch", dependencies: [.product(name: "Bread", package: "sandwich")]), + TargetDescription(name: "Lunch", dependencies: [.product(name: "Bread", package: "sandwich")]) ] ), ], @@ -1552,7 +1554,7 @@ struct ModulesGraphTests { path: "/controls", products: [ProductDescription(name: "Valve", type: .library(.automatic), targets: ["Valve"])], targets: [ - TargetDescription(name: "Valve"), + TargetDescription(name: "Valve") ] ), Manifest.createRootManifest( @@ -1562,9 +1564,13 @@ struct ModulesGraphTests { // there's a lexically-close product name in a different package. dependencies: [.fileSystem(path: "/controls")], targets: [ - TargetDescription(name: "Chart", dependencies: [ - "Valv", - .product(name: "Valve", package: "controls")]), + TargetDescription( + name: "Chart", + dependencies: [ + "Valv", + .product(name: "Valve", package: "controls"), + ] + ), TargetDescription(name: "Value"), ] ), @@ -1596,14 +1602,14 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", targets: [ - TargetDescription(name: "Foo", dependencies: ["Qux"]), + TargetDescription(name: "Foo", dependencies: ["Qux"]) ] ), Manifest.createRootManifest( displayName: "Bar", path: "/Bar", targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ], @@ -1634,13 +1640,13 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["FooTarget"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["FooTarget"]) ], targets: [ TargetDescription(name: "FooTarget", dependencies: []), TargetDescription(name: "FooTests", dependencies: ["Foo"], type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -1671,7 +1677,7 @@ struct ModulesGraphTests { TargetDescription(name: "XYZ", dependencies: [], type: .executable), TargetDescription(name: "XYZTests", dependencies: ["XYZ"], type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -1694,13 +1700,13 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ], targets: [ TargetDescription(name: "Foo", dependencies: []), TargetDescription(name: "FooTests", dependencies: ["Foo"], type: .test), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -1723,9 +1729,9 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_2, targets: [ - TargetDescription(name: "FooTarget", dependencies: [.product(name: "Barx", package: "Bar")]), + TargetDescription(name: "FooTarget", dependencies: [.product(name: "Barx", package: "Bar")]) ] - ), + ) ], observabilityScope: observability.topScope ) @@ -1754,10 +1760,10 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_2, targets: [ - TargetDescription(name: "FooTarget", dependencies: [.product(name: "Barx")]), + TargetDescription(name: "FooTarget", dependencies: [.product(name: "Barx")]) ], traits: [] - ), + ) ], observabilityScope: observability.topScope ) @@ -1794,17 +1800,17 @@ struct ModulesGraphTests { .localSourceControl(path: "/FizPath", requirement: .upToNextMajor(from: "1.1.2")), ], targets: [ - TargetDescription(name: "Foo", dependencies: ["BarLib", "Biz", "FizLib"]), + TargetDescription(name: "Foo", dependencies: ["BarLib", "Biz", "FizLib"]) ] ), Manifest.createLocalSourceControlManifest( displayName: "Bar", path: "/Bar", products: [ - ProductDescription(name: "BarLib", type: .library(.automatic), targets: ["BarLib"]), + ProductDescription(name: "BarLib", type: .library(.automatic), targets: ["BarLib"]) ], targets: [ - TargetDescription(name: "BarLib"), + TargetDescription(name: "BarLib") ] ), Manifest.createLocalSourceControlManifest( @@ -1812,10 +1818,10 @@ struct ModulesGraphTests { path: "/BizPath", version: "1.2.3", products: [ - ProductDescription(name: "Biz", type: .library(.automatic), targets: ["Biz"]), + ProductDescription(name: "Biz", type: .library(.automatic), targets: ["Biz"]) ], targets: [ - TargetDescription(name: "Biz"), + TargetDescription(name: "Biz") ] ), Manifest.createLocalSourceControlManifest( @@ -1823,10 +1829,10 @@ struct ModulesGraphTests { path: "/FizPath", version: "1.2.3", products: [ - ProductDescription(name: "FizLib", type: .library(.automatic), targets: ["FizLib"]), + ProductDescription(name: "FizLib", type: .library(.automatic), targets: ["FizLib"]) ], targets: [ - TargetDescription(name: "FizLib"), + TargetDescription(name: "FizLib") ] ), ], @@ -1836,20 +1842,20 @@ struct ModulesGraphTests { try expectDiagnostics(observability.diagnostics) { result in result.checkUnordered( diagnostic: """ - dependency 'BarLib' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "BarLib", package: "Bar")' - """, + dependency 'BarLib' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "BarLib", package: "Bar")' + """, severity: .error ) result.checkUnordered( diagnostic: """ - dependency 'Biz' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "Biz", package: "BizPath")' - """, + dependency 'Biz' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "Biz", package: "BizPath")' + """, severity: .error ) result.checkUnordered( diagnostic: """ - dependency 'FizLib' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "FizLib", package: "FizPath")' - """, + dependency 'FizLib' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "FizLib", package: "FizPath")' + """, severity: .error ) } @@ -1872,20 +1878,20 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_2, dependencies: [ - .localSourceControl(deprecatedName: "UnBar", path: "/Bar", requirement: .branch("master")), + .localSourceControl(deprecatedName: "UnBar", path: "/Bar", requirement: .branch("master")) ], targets: [ - TargetDescription(name: "Foo", dependencies: [.product(name: "BarProduct", package: "UnBar")]), + TargetDescription(name: "Foo", dependencies: [.product(name: "BarProduct", package: "UnBar")]) ] ), Manifest.createLocalSourceControlManifest( displayName: "UnBar", path: "/Bar", products: [ - ProductDescription(name: "BarProduct", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "BarProduct", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ], @@ -1919,37 +1925,37 @@ struct ModulesGraphTests { .localSourceControl(path: "/Biz", requirement: .upToNextMajor(from: "1.0.0")), ], targets: [ - TargetDescription(name: "Foo", dependencies: ["BarLibrary"]), + TargetDescription(name: "Foo", dependencies: ["BarLibrary"]) ] ), Manifest.createFileSystemManifest( displayName: "Biz", path: "/Biz", products: [ - ProductDescription(name: "biz", type: .executable, targets: ["Biz"]), + ProductDescription(name: "biz", type: .executable, targets: ["Biz"]) ], targets: [ - TargetDescription(name: "Biz"), + TargetDescription(name: "Biz") ] ), Manifest.createFileSystemManifest( displayName: "Bar", path: "/Bar", products: [ - ProductDescription(name: "BarLibrary", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "BarLibrary", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), Manifest.createFileSystemManifest( displayName: "Baz", path: "/Baz", products: [ - ProductDescription(name: "BazLibrary", type: .library(.automatic), targets: ["Baz"]), + ProductDescription(name: "BazLibrary", type: .library(.automatic), targets: ["Baz"]) ], targets: [ - TargetDescription(name: "Baz"), + TargetDescription(name: "Baz") ] ), ], @@ -1962,9 +1968,9 @@ struct ModulesGraphTests { #expect(metadata.packageIdentity == "foo") let packageKind = try #require(metadata.packageKind) #expect(packageKind.isRoot) -#if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - result.check(diagnostic: "dependency 'biz' is not used by any target", severity: .warning) -#endif + #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION + result.check(diagnostic: "dependency 'biz' is not used by any target", severity: .warning) + #endif } } @@ -1984,10 +1990,10 @@ struct ModulesGraphTests { displayName: "Bar", path: "/Bar", dependencies: [ - .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), Manifest.createFileSystemManifest( @@ -2021,7 +2027,7 @@ struct ModulesGraphTests { .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")), // Baz is unused by all targets in this package, and thus should be omitted // with `pruneDependencies` enabled. - .localSourceControl(path: "/Baz", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Baz", requirement: .upToNextMajor(from: "1.0.0")), ], targets: [ TargetDescription( @@ -2034,9 +2040,9 @@ struct ModulesGraphTests { // is not enabled by default, the package dependency `Foo` will // be omitted since `pruneDependencies` is enabled. condition: .init(traits: ["Trait2"]) - ), + ) ] - ), + ) ], traits: [.init(name: "default", enabledTraits: ["Trait1"]), "Trait1", "Trait2"], pruneDependencies: true @@ -2045,26 +2051,26 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", products: [ - .init(name: "FooLibrary", type: .library(.automatic), targets: ["Foo"]), + .init(name: "FooLibrary", type: .library(.automatic), targets: ["Foo"]) ], targets: [ TargetDescription( name: "Foo", dependencies: [] - ), + ) ] ), Manifest.createFileSystemManifest( displayName: "Baz", path: "/Baz", products: [ - .init(name: "BazLibrary", type: .library(.automatic), targets: ["Baz"]), + .init(name: "BazLibrary", type: .library(.automatic), targets: ["Baz"]) ], targets: [ TargetDescription( name: "Baz", dependencies: [] - ), + ) ] ), @@ -2094,7 +2100,7 @@ struct ModulesGraphTests { displayName: "Start", path: "/Start", dependencies: [ - .localSourceControl(path: "/Dep1", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Dep1", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription(name: "Foo", dependencies: ["BazLibrary"]), @@ -2105,13 +2111,13 @@ struct ModulesGraphTests { displayName: "Dep1", path: "/Dep1", dependencies: [ - .localSourceControl(path: "/Dep2", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Dep2", requirement: .upToNextMajor(from: "1.0.0")) ], products: [ - ProductDescription(name: "BazLibrary", type: .library(.automatic), targets: ["Baz"]), + ProductDescription(name: "BazLibrary", type: .library(.automatic), targets: ["Baz"]) ], targets: [ - TargetDescription(name: "Baz", dependencies: ["FooLibrary"]), + TargetDescription(name: "Baz", dependencies: ["FooLibrary"]) ] ), Manifest.createFileSystemManifest( @@ -2163,27 +2169,27 @@ struct ModulesGraphTests { .localSourceControl(path: bazPkg, requirement: .upToNextMajor(from: "1.0.0")), ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar"]), + TargetDescription(name: "Foo", dependencies: ["Bar"]) ] ), Manifest.createFileSystemManifest( displayName: "Bar", path: barPkg, products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), Manifest.createFileSystemManifest( displayName: "Baz", path: bazPkg, products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Baz"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Baz"]) ], targets: [ - TargetDescription(name: "Baz"), + TargetDescription(name: "Baz") ] ), ], @@ -2216,7 +2222,7 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription(name: "Foo", dependencies: ["Bar"]), @@ -2253,7 +2259,7 @@ struct ModulesGraphTests { TargetDescription( name: "Bar3", settings: [ - .init(tool: .swift, kind: .unsafeFlags([])), + .init(tool: .swift, kind: .unsafeFlags([])) ] ), TargetDescription( @@ -2277,7 +2283,6 @@ struct ModulesGraphTests { #expect(observability.diagnostics.count == 0) } - @Test func testUnsafeFlagsEnabled() throws { let observability = try loadUnsafeModulesGraph(toolsVersion: .v6_1) @@ -2286,24 +2291,30 @@ struct ModulesGraphTests { try expectDiagnostics(observability.diagnostics) { result in var expectedMetadata = ObservabilityMetadata() expectedMetadata.moduleName = "Foo2" - let diagnostic1 = try #require(result.checkUnordered( - diagnostic: .contains("the target 'Bar2' in product 'TransitiveBar' contains unsafe build flags"), - severity: .error - )) + let diagnostic1 = try #require( + result.checkUnordered( + diagnostic: .contains("the target 'Bar2' in product 'TransitiveBar' contains unsafe build flags"), + severity: .error + ) + ) let diagnostic1_metadata = try #require(diagnostic1.metadata) #expect(diagnostic1_metadata.moduleName == "Foo2") - let diagnostic2 = try #require(result.checkUnordered( - diagnostic: .contains("the target 'Bar' in product 'Bar' contains unsafe build flags"), - severity: .error - )) + let diagnostic2 = try #require( + result.checkUnordered( + diagnostic: .contains("the target 'Bar' in product 'Bar' contains unsafe build flags"), + severity: .error + ) + ) let diagnostic2_metadata = try #require(diagnostic2.metadata) #expect(diagnostic2_metadata.moduleName == "Foo") - let diagnostic3 = try #require(result.checkUnordered( - diagnostic: .contains("the target 'Bar2' in product 'Bar' contains unsafe build flags"), - severity: .error - )) + let diagnostic3 = try #require( + result.checkUnordered( + diagnostic: .contains("the target 'Bar2' in product 'Bar' contains unsafe build flags"), + severity: .error + ) + ) let diagnostic3_metadata = try #require(diagnostic3.metadata) #expect(diagnostic3_metadata.moduleName == "Foo") } @@ -2327,23 +2338,36 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", dependencies: [ - .fileSystem(path: "/Biz"), - ], - targets: [ - TargetDescription(name: "Foo", dependencies: [ - .target(name: "Bar", condition: PackageConditionDescription( - platformNames: ["linux"], - config: nil - )), - .byName(name: "Baz", condition: PackageConditionDescription( - platformNames: [], - config: "debug" - )), - .product(name: "Biz", package: "Biz", condition: PackageConditionDescription( - platformNames: ["watchos", "ios"], - config: "release" - )), - ]), + .fileSystem(path: "/Biz") + ], + targets: [ + TargetDescription( + name: "Foo", + dependencies: [ + .target( + name: "Bar", + condition: PackageConditionDescription( + platformNames: ["linux"], + config: nil + ) + ), + .byName( + name: "Baz", + condition: PackageConditionDescription( + platformNames: [], + config: "debug" + ) + ), + .product( + name: "Biz", + package: "Biz", + condition: PackageConditionDescription( + platformNames: ["watchos", "ios"], + config: "release" + ) + ), + ] + ), TargetDescription(name: "Bar"), TargetDescription(name: "Baz"), ], @@ -2353,10 +2377,10 @@ struct ModulesGraphTests { displayName: "Biz", path: "/Biz", products: [ - ProductDescription(name: "Biz", type: .library(.automatic), targets: ["Biz"]), + ProductDescription(name: "Biz", type: .library(.automatic), targets: ["Biz"]) ], targets: [ - TargetDescription(name: "Biz"), + TargetDescription(name: "Biz") ] ), ], @@ -2410,12 +2434,15 @@ struct ModulesGraphTests { path: "/Root", toolsVersion: .v5_2, dependencies: [ - .localSourceControl(path: "/Immediate", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Immediate", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Root", dependencies: [ - .product(name: "ImmediateUsed", package: "Immediate"), - ]), + TargetDescription( + name: "Root", + dependencies: [ + .product(name: "ImmediateUsed", package: "Immediate") + ] + ) ] ), Manifest.createFileSystemManifest( @@ -2445,13 +2472,19 @@ struct ModulesGraphTests { ), ], targets: [ - TargetDescription(name: "ImmediateUsed", dependencies: [ - .product(name: "TransitiveUsed", package: "Transitive"), - ]), - TargetDescription(name: "ImmediateUnused", dependencies: [ - .product(name: "TransitiveUnused", package: "Transitive"), - .product(name: "Nonexistent", package: "Nonexistent"), - ]), + TargetDescription( + name: "ImmediateUsed", + dependencies: [ + .product(name: "TransitiveUsed", package: "Transitive") + ] + ), + TargetDescription( + name: "ImmediateUnused", + dependencies: [ + .product(name: "TransitiveUnused", package: "Transitive"), + .product(name: "Nonexistent", package: "Nonexistent"), + ] + ), ] ), Manifest.createFileSystemManifest( @@ -2462,20 +2495,23 @@ struct ModulesGraphTests { .localSourceControl( path: "/Nonexistent", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], products: [ ProductDescription( name: "TransitiveUsed", type: .library(.automatic), targets: ["TransitiveUsed"] - ), + ) ], targets: [ TargetDescription(name: "TransitiveUsed"), - TargetDescription(name: "TransitiveUnused", dependencies: [ - .product(name: "Nonexistent", package: "Nonexistent"), - ]), + TargetDescription( + name: "TransitiveUnused", + dependencies: [ + .product(name: "Nonexistent", package: "Nonexistent") + ] + ), ] ), ], @@ -2488,32 +2524,32 @@ struct ModulesGraphTests { @Test func resolvedPackagesStoreIsResilientAgainstDupes() throws { let json = """ - { - "version": 1, - "object": { - "pins": [ - { - "package": "Yams", - "repositoryURL": "https://github.com/jpsim/yams", - "state": { - "branch": null, - "revision": "b08dba4bcea978bf1ad37703a384097d3efce5af", - "version": "1.0.2" - } - }, - { - "package": "Yams", - "repositoryURL": "https://github.com/jpsim/yams", - "state": { - "branch": null, - "revision": "b08dba4bcea978bf1ad37703a384097d3efce5af", - "version": "1.0.2" - } + { + "version": 1, + "object": { + "pins": [ + { + "package": "Yams", + "repositoryURL": "https://github.com/jpsim/yams", + "state": { + "branch": null, + "revision": "b08dba4bcea978bf1ad37703a384097d3efce5af", + "version": "1.0.2" + } + }, + { + "package": "Yams", + "repositoryURL": "https://github.com/jpsim/yams", + "state": { + "branch": null, + "revision": "b08dba4bcea978bf1ad37703a384097d3efce5af", + "version": "1.0.2" + } + } + ] } - ] - } - } - """ + } + """ let fs = InMemoryFileSystem() let packageResolvedFile = AbsolutePath("/Package.resolved") @@ -2561,57 +2597,57 @@ struct ModulesGraphTests { .localSourceControl(path: "/F", requirement: .upToNextMajor(from: "1.0.0")), ], targets: [ - TargetDescription(name: "A", dependencies: []), + TargetDescription(name: "A", dependencies: []) ] ), Manifest.createFileSystemManifest( displayName: "B", path: "/B", products: [ - ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]), + ProductDescription(name: "B", type: .library(.automatic), targets: ["B"]) ], targets: [ - TargetDescription(name: "B"), + TargetDescription(name: "B") ] ), Manifest.createFileSystemManifest( displayName: "C", path: "/C", products: [ - ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]), + ProductDescription(name: "C", type: .library(.automatic), targets: ["C"]) ], targets: [ - TargetDescription(name: "C"), + TargetDescription(name: "C") ] ), Manifest.createFileSystemManifest( displayName: "D", path: "/D", products: [ - ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]), + ProductDescription(name: "D", type: .library(.automatic), targets: ["D"]) ], targets: [ - TargetDescription(name: "D"), + TargetDescription(name: "D") ] ), Manifest.createFileSystemManifest( displayName: "E", path: "/E", products: [ - ProductDescription(name: "E", type: .library(.automatic), targets: ["E"]), + ProductDescription(name: "E", type: .library(.automatic), targets: ["E"]) ], targets: [ - TargetDescription(name: "E"), + TargetDescription(name: "E") ] ), Manifest.createFileSystemManifest( displayName: "F", path: "/F", products: [ - ProductDescription(name: "F", type: .library(.automatic), targets: ["F"]), + ProductDescription(name: "F", type: .library(.automatic), targets: ["F"]) ], targets: [ - TargetDescription(name: "F"), + TargetDescription(name: "F") ] ), ], @@ -2644,10 +2680,10 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5, dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar"]), + TargetDescription(name: "Foo", dependencies: ["Bar"]) ] ), Manifest.createFileSystemManifest( @@ -2655,10 +2691,10 @@ struct ModulesGraphTests { path: "/Bar", toolsVersion: .v5, products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ], @@ -2685,10 +2721,10 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5, dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Unknown"]), + TargetDescription(name: "Foo", dependencies: ["Unknown"]) ] ), Manifest.createFileSystemManifest( @@ -2696,10 +2732,10 @@ struct ModulesGraphTests { path: "/Bar", toolsVersion: .v5, products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ], @@ -2709,8 +2745,8 @@ struct ModulesGraphTests { try expectDiagnostics(observability.diagnostics) { result in result.check( diagnostic: """ - product 'Unknown' required by package 'foo' target 'Foo' not found. - """, + product 'Unknown' required by package 'foo' target 'Foo' not found. + """, severity: .error ) } @@ -2733,10 +2769,10 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_2, dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar"]), + TargetDescription(name: "Foo", dependencies: ["Bar"]) ] ), Manifest.createFileSystemManifest( @@ -2744,10 +2780,10 @@ struct ModulesGraphTests { path: "/Bar", toolsVersion: .v5_2, products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ], @@ -2774,10 +2810,10 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_2, dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Unknown"]), + TargetDescription(name: "Foo", dependencies: ["Unknown"]) ] ), Manifest.createFileSystemManifest( @@ -2785,10 +2821,10 @@ struct ModulesGraphTests { path: "/Bar", toolsVersion: .v5_2, products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ], @@ -2798,8 +2834,8 @@ struct ModulesGraphTests { try expectDiagnostics(observability.diagnostics) { result in result.check( diagnostic: """ - product 'Unknown' required by package 'foo' target 'Foo' not found. - """, + product 'Unknown' required by package 'foo' target 'Foo' not found. + """, severity: .error ) } @@ -2819,10 +2855,10 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_2, dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["ProductBar"]), + TargetDescription(name: "Foo", dependencies: ["ProductBar"]) ] ), Manifest.createFileSystemManifest( @@ -2830,10 +2866,10 @@ struct ModulesGraphTests { path: "/Bar", toolsVersion: .v5_2, products: [ - ProductDescription(name: "ProductBar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "ProductBar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ] @@ -2844,8 +2880,8 @@ struct ModulesGraphTests { try expectDiagnostics(observability.diagnostics) { result in result.check( diagnostic: """ - dependency 'ProductBar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "ProductBar", package: "Bar")' - """, + dependency 'ProductBar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "ProductBar", package: "Bar")' + """, severity: .error ) } @@ -2856,9 +2892,9 @@ struct ModulesGraphTests { do { let fixedManifests = try [ manifests[0].withTargets([ - TargetDescription(name: "Foo", dependencies: [.product(name: "ProductBar", package: "Bar")]), + TargetDescription(name: "Foo", dependencies: [.product(name: "ProductBar", package: "Bar")]) ]), - manifests[1], // same + manifests[1], // same ] let observability = ObservabilitySystem.makeForTesting() @@ -2890,10 +2926,10 @@ struct ModulesGraphTests { deprecatedName: "Bar", path: "/Bar", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["ProductBar"]), + TargetDescription(name: "Foo", dependencies: ["ProductBar"]) ] ), Manifest.createFileSystemManifest( @@ -2901,10 +2937,10 @@ struct ModulesGraphTests { path: "/Bar", toolsVersion: .v5_2, products: [ - ProductDescription(name: "ProductBar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "ProductBar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ] @@ -2915,8 +2951,8 @@ struct ModulesGraphTests { try expectDiagnostics(observability.diagnostics) { result in result.check( diagnostic: """ - dependency 'ProductBar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "ProductBar", package: "Bar")' - """, + dependency 'ProductBar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "ProductBar", package: "Bar")' + """, severity: .error ) } @@ -2927,9 +2963,9 @@ struct ModulesGraphTests { do { let fixedManifests = try [ manifests[0].withTargets([ - TargetDescription(name: "Foo", dependencies: [.product(name: "ProductBar", package: "Bar")]), + TargetDescription(name: "Foo", dependencies: [.product(name: "ProductBar", package: "Bar")]) ]), - manifests[1], // same + manifests[1], // same ] let observability = ObservabilitySystem.makeForTesting() @@ -2956,10 +2992,10 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_2, dependencies: [ - .localSourceControl(path: "/Some-Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Some-Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar"]), + TargetDescription(name: "Foo", dependencies: ["Bar"]) ] ), Manifest.createFileSystemManifest( @@ -2967,10 +3003,10 @@ struct ModulesGraphTests { path: "/Some-Bar", toolsVersion: .v5_2, products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ] @@ -2981,8 +3017,8 @@ struct ModulesGraphTests { try expectDiagnostics(observability.diagnostics) { result in result.check( diagnostic: """ - dependency 'Bar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "Bar", package: "Some-Bar")' - """, + dependency 'Bar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "Bar", package: "Some-Bar")' + """, severity: .error ) } @@ -2993,9 +3029,9 @@ struct ModulesGraphTests { do { let fixedManifests = try [ manifests[0].withTargets([ - TargetDescription(name: "Foo", dependencies: [.product(name: "Bar", package: "Some-Bar")]), + TargetDescription(name: "Foo", dependencies: [.product(name: "Bar", package: "Some-Bar")]) ]), - manifests[1], // same + manifests[1], // same ] let observability = ObservabilitySystem.makeForTesting() @@ -3022,10 +3058,10 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_2, dependencies: [ - .localSourceControl(path: "/Some-Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Some-Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["ProductBar"]), + TargetDescription(name: "Foo", dependencies: ["ProductBar"]) ] ), Manifest.createFileSystemManifest( @@ -3033,10 +3069,10 @@ struct ModulesGraphTests { path: "/Some-Bar", toolsVersion: .v5_2, products: [ - ProductDescription(name: "ProductBar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "ProductBar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ] @@ -3047,8 +3083,8 @@ struct ModulesGraphTests { try expectDiagnostics(observability.diagnostics) { result in let diagnostic = result.check( diagnostic: """ - dependency 'ProductBar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "ProductBar", package: "Some-Bar")' - """, + dependency 'ProductBar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "ProductBar", package: "Some-Bar")' + """, severity: .error ) #expect(diagnostic?.metadata?.packageIdentity == .plain("foo")) @@ -3060,9 +3096,9 @@ struct ModulesGraphTests { do { let fixedManifests = try [ manifests[0].withTargets([ - TargetDescription(name: "Foo", dependencies: [.product(name: "ProductBar", package: "Foo-Bar")]), + TargetDescription(name: "Foo", dependencies: [.product(name: "ProductBar", package: "Foo-Bar")]) ]), - manifests[1], // same + manifests[1], // same ] let observability = ObservabilitySystem.makeForTesting() @@ -3095,10 +3131,10 @@ struct ModulesGraphTests { deprecatedName: "Bar", path: "/Some-Bar", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["Bar"]), + TargetDescription(name: "Foo", dependencies: ["Bar"]) ] ), Manifest.createFileSystemManifest( @@ -3106,10 +3142,10 @@ struct ModulesGraphTests { path: "/Some-Bar", toolsVersion: .v5_2, products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ] @@ -3139,10 +3175,10 @@ struct ModulesGraphTests { deprecatedName: "Bar", path: "/Some-Bar", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], targets: [ - TargetDescription(name: "Foo", dependencies: ["ProductBar"]), + TargetDescription(name: "Foo", dependencies: ["ProductBar"]) ] ), Manifest.createFileSystemManifest( @@ -3150,10 +3186,10 @@ struct ModulesGraphTests { path: "/Some-Bar", toolsVersion: .v5_2, products: [ - ProductDescription(name: "ProductBar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "ProductBar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ] @@ -3164,8 +3200,8 @@ struct ModulesGraphTests { try expectDiagnostics(observability.diagnostics) { result in let diagnostic = result.check( diagnostic: """ - dependency 'ProductBar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "ProductBar", package: "Bar")' - """, + dependency 'ProductBar' in target 'Foo' requires explicit declaration; reference the package in the target dependency with '.product(name: "ProductBar", package: "Bar")' + """, severity: .error ) #expect(diagnostic?.metadata?.packageIdentity == .plain("foo")) @@ -3177,9 +3213,9 @@ struct ModulesGraphTests { do { let fixedManifests = try [ manifests[0].withTargets([ - TargetDescription(name: "Foo", dependencies: [.product(name: "ProductBar", package: "Some-Bar")]), + TargetDescription(name: "Foo", dependencies: [.product(name: "ProductBar", package: "Some-Bar")]) ]), - manifests[1], // same + manifests[1], // same ] let observability = ObservabilitySystem.makeForTesting() @@ -3218,7 +3254,7 @@ struct ModulesGraphTests { .product(name: "Product", package: "Alias"), .product(name: "Unrelated", package: "Unrelated"), ] - ), + ) ] ) // Make sure aliases are found properly and do not fall back to pre‐5.2 behavior, leaking across onto other @@ -3226,12 +3262,13 @@ struct ModulesGraphTests { let required = try manifest.dependenciesRequired(for: .everything) let unrelated = try #require( required - .first(where: { $0.nameForModuleDependencyResolutionOnly == "Unrelated" })) + .first(where: { $0.nameForModuleDependencyResolutionOnly == "Unrelated" }) + ) let requestedProducts = unrelated.productFilter -#if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - // Unrelated should not have been asked for Product, because it should know Product comes from Identity. - #expect(!requestedProducts.contains("Product"), "Product requests are leaking.") -#endif + #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION + // Unrelated should not have been asked for Product, because it should know Product comes from Identity. + #expect(!requestedProducts.contains("Product"), "Product requests are leaking.") + #endif } @Test @@ -3268,7 +3305,8 @@ struct ModulesGraphTests { PackageModel.Platform.visionOS: PlatformVersion("1.0"), ] - let expectedPlatformsForTests = customXCTestMinimumDeploymentTargets + let expectedPlatformsForTests = + customXCTestMinimumDeploymentTargets .reduce(into: [PackageModel.Platform: PlatformVersion]()) { partialResult, entry in if entry.value > entry.key.oldestSupportedVersion { partialResult[entry.key] = entry.value @@ -3282,7 +3320,7 @@ struct ModulesGraphTests { let manifest = try Manifest.createRootManifest( displayName: "pkg", platforms: [ - PlatformDescription(name: "macos", version: "10.14", options: ["option1"]), + PlatformDescription(name: "macos", version: "10.14", options: ["option1"]) ], products: [ ProductDescription(name: "foo", type: .library(.automatic), targets: ["foo"]), @@ -3317,7 +3355,7 @@ struct ModulesGraphTests { try PackageGraphTester(graph) { result in let expectedDeclaredPlatforms = [ - "macos": "10.14", + "macos": "10.14" ] // default platforms will be auto-added during package build @@ -3353,25 +3391,25 @@ struct ModulesGraphTests { target.checkDerivedPlatformOptions(.macOS, options: ["option1"]) target.checkDerivedPlatformOptions(.iOS, options: []) } - try result.checkProduct("foo") { product in + try result.checkProduct("foo") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) product.checkDerivedPlatformOptions(.macOS, options: ["option1"]) product.checkDerivedPlatformOptions(.iOS, options: []) } - try result.checkProduct("bar") { product in + try result.checkProduct("bar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) product.checkDerivedPlatformOptions(.macOS, options: ["option1"]) product.checkDerivedPlatformOptions(.iOS, options: []) } - try result.checkProduct("cbar") { product in + try result.checkProduct("cbar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) product.checkDerivedPlatformOptions(.macOS, options: ["option1"]) product.checkDerivedPlatformOptions(.iOS, options: []) } - try result.checkProduct("multi-target") { product in + try result.checkProduct("multi-target") { product in var expected = expectedDerivedPlatforms for item in [PackageModel.Platform.macOS, .iOS, .tvOS, .watchOS] { expected[item.name] = expectedPlatformsForTests[item]?.versionString @@ -3435,15 +3473,15 @@ struct ModulesGraphTests { target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - try result.checkProduct("foo") { product in + try result.checkProduct("foo") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } - try result.checkProduct("bar") { product in + try result.checkProduct("bar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } - try result.checkProduct("cbar") { product in + try result.checkProduct("cbar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } @@ -3455,10 +3493,10 @@ struct ModulesGraphTests { let manifest = try Manifest.createRootManifest( displayName: "pkg", platforms: [ - PlatformDescription(name: "ios", version: "15.0"), + PlatformDescription(name: "ios", version: "15.0") ], products: [ - ProductDescription(name: "cbar", type: .library(.automatic), targets: ["cbar"]), + ProductDescription(name: "cbar", type: .library(.automatic), targets: ["cbar"]) ], targets: [ TargetDescription(name: "cbar"), @@ -3477,7 +3515,7 @@ struct ModulesGraphTests { try PackageGraphTester(graph) { result in let expectedDeclaredPlatforms = [ - "ios": "15.0", + "ios": "15.0" ] var expectedDerivedPlatforms = defaultDerivedPlatforms.merging( @@ -3502,7 +3540,7 @@ struct ModulesGraphTests { target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - try result.checkProduct("cbar") { product in + try result.checkProduct("cbar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } @@ -3537,13 +3575,13 @@ struct ModulesGraphTests { let manifest = try Manifest.createRootManifest( displayName: "pkg", platforms: [ - PlatformDescription(name: "customos", version: "1.0"), + PlatformDescription(name: "customos", version: "1.0") ], products: [ - ProductDescription(name: "foo", type: .library(.automatic), targets: ["foo"]), + ProductDescription(name: "foo", type: .library(.automatic), targets: ["foo"]) ], targets: [ - TargetDescription(name: "foo", type: .system), + TargetDescription(name: "foo", type: .system) ] ) @@ -3557,7 +3595,7 @@ struct ModulesGraphTests { try PackageGraphTester(graph) { result in let expectedDeclaredPlatforms = [ - "customos": "1.0", + "customos": "1.0" ] // default platforms will be auto-added during package build @@ -3570,7 +3608,7 @@ struct ModulesGraphTests { target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - try result.checkProduct("foo") { product in + try result.checkProduct("foo") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } @@ -3586,10 +3624,10 @@ struct ModulesGraphTests { PlatformDescription(name: "anothercustomos", version: "2.3"), ], products: [ - ProductDescription(name: "foo", type: .library(.automatic), targets: ["foo"]), + ProductDescription(name: "foo", type: .library(.automatic), targets: ["foo"]) ], targets: [ - TargetDescription(name: "foo", type: .system), + TargetDescription(name: "foo", type: .system) ] ) @@ -3617,7 +3655,7 @@ struct ModulesGraphTests { target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - try result.checkProduct("foo") { product in + try result.checkProduct("foo") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } @@ -3646,7 +3684,7 @@ struct ModulesGraphTests { displayName: "Foo", path: "/Foo", dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ TargetDescription(name: "Foo", dependencies: ["Bar"]), @@ -3668,13 +3706,13 @@ struct ModulesGraphTests { TargetDescription( name: "Bar", settings: [ - .init(tool: .swift, kind: .enableUpcomingFeature("ConciseMagicFile")), + .init(tool: .swift, kind: .enableUpcomingFeature("ConciseMagicFile")) ] ), TargetDescription( name: "Bar2", settings: [ - .init(tool: .swift, kind: .enableUpcomingFeature("UnknownToTheseTools")), + .init(tool: .swift, kind: .enableUpcomingFeature("UnknownToTheseTools")) ] ), TargetDescription( @@ -3714,10 +3752,10 @@ struct ModulesGraphTests { path: "/Foo", toolsVersion: .v5_9, dependencies: [ - .fileSystem(deprecatedName: "Bar", path: "/Bar2"), + .fileSystem(deprecatedName: "Bar", path: "/Bar2") ], targets: [ - TargetDescription(name: "Foo", dependencies: [.product(name: "Bar", package: "BAR")]), + TargetDescription(name: "Foo", dependencies: [.product(name: "Bar", package: "BAR")]) ] ), Manifest.createFileSystemManifest( @@ -3725,10 +3763,10 @@ struct ModulesGraphTests { path: "/Bar2", toolsVersion: .v5_9, products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), + ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]) ], targets: [ - TargetDescription(name: "Bar"), + TargetDescription(name: "Bar") ] ), ], @@ -3754,7 +3792,7 @@ struct ModulesGraphTests { displayName: "aaa", path: "/aaa", dependencies: [ - .localSourceControl(path: "/zzz", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/zzz", requirement: .upToNextMajor(from: "1.0.0")) ], products: [], targets: [ @@ -3762,7 +3800,7 @@ struct ModulesGraphTests { name: "aaa", dependencies: ["mmm"], type: .executable - ), + ) ] ), Manifest.createFileSystemManifest( @@ -3773,12 +3811,12 @@ struct ModulesGraphTests { name: "zzz", type: .library(.automatic), targets: ["zzz"] - ), + ) ], targets: [ TargetDescription( name: "zzz" - ), + ) ] ), ], diff --git a/Tests/PackageGraphTests/PubGrubTests.swift b/Tests/PackageGraphTests/PubGrubTests.swift index ba04635930d..81cfb4119d6 100644 --- a/Tests/PackageGraphTests/PubGrubTests.swift +++ b/Tests/PackageGraphTests/PubGrubTests.swift @@ -101,44 +101,53 @@ final class PubGrubTests: XCTestCase { // a^1.0.0 ∩ ¬a@1.5.0 → a >=1.0.0 <1.5.0 XCTAssertEqual( Term("a^1.0.0").intersect(with: Term("¬a@1.5.0")), - Term("a-1.0.0-1.5.0")) + Term("a-1.0.0-1.5.0") + ) // a^1.0.0 ∩ a >=1.5.0 <3.0.0 → a^1.5.0 XCTAssertEqual( Term("a^1.0.0").intersect(with: Term("a-1.5.0-3.0.0")), - Term("a^1.5.0")) + Term("a^1.5.0") + ) // ¬a^1.0.0 ∩ ¬a >=1.5.0 <3.0.0 → ¬a >=1.0.0 <3.0.0 XCTAssertEqual( Term("¬a^1.0.0").intersect(with: Term("¬a-1.5.0-3.0.0")), - Term("¬a-1.0.0-3.0.0")) + Term("¬a-1.0.0-3.0.0") + ) XCTAssertEqual( Term("a^1.0.0").intersect(with: Term("a^1.0.0")), - Term("a^1.0.0")) + Term("a^1.0.0") + ) XCTAssertEqual( Term("¬a^1.0.0").intersect(with: Term("¬a^1.0.0")), - Term("¬a^1.0.0")) + Term("¬a^1.0.0") + ) XCTAssertNil(Term("a^1.0.0").intersect(with: Term("¬a^1.0.0"))) XCTAssertNil(Term("a@1.0.0").difference(with: Term("a@1.0.0"))) XCTAssertEqual( Term("¬a^1.0.0").intersect(with: Term("a^2.0.0")), - Term("a^2.0.0")) + Term("a^2.0.0") + ) XCTAssertEqual( Term("a^2.0.0").intersect(with: Term("¬a^1.0.0")), - Term("a^2.0.0")) + Term("a^2.0.0") + ) XCTAssertEqual( Term("¬a^1.0.0").intersect(with: Term("¬a^1.0.0")), - Term("¬a^1.0.0")) + Term("¬a^1.0.0") + ) XCTAssertEqual( Term("¬a@1.0.0").intersect(with: Term("¬a@1.0.0")), - Term("¬a@1.0.0")) + Term("¬a@1.0.0") + ) // Check difference. let anyA = Term(.empty(package: "a"), .any) @@ -183,7 +192,7 @@ final class PubGrubTests: XCTestCase { func testTermIsValidDecision() { let solution100_150 = PartialSolution(assignments: [ .derivation("a^1.0.0", cause: _cause, decisionLevel: 1), - .derivation("a^1.5.0", cause: _cause, decisionLevel: 2) + .derivation("a^1.5.0", cause: _cause, decisionLevel: 2), ]) let allSatisfied = Term("a@1.6.0") @@ -193,26 +202,33 @@ final class PubGrubTests: XCTestCase { } func testIncompatibilityNormalizeTermsOnInit() async throws { - let i1 = try Incompatibility(Term("a^1.0.0"), Term("a^1.5.0"), Term("¬b@1.0.0"), - root: rootNode) + let i1 = try Incompatibility( + Term("a^1.0.0"), + Term("a^1.5.0"), + Term("¬b@1.0.0"), + root: rootNode + ) XCTAssertEqual(i1.terms.count, 2) let a1 = i1.terms.first { $0.node.package == "a" } let b1 = i1.terms.first { $0.node.package == "b" } XCTAssertEqual(a1?.requirement, v1_5Range) XCTAssertEqual(b1?.requirement, .exact(v1)) - let i2 = try Incompatibility(Term("¬a^1.0.0"), Term("a^2.0.0"), - root: rootNode) + let i2 = try Incompatibility( + Term("¬a^1.0.0"), + Term("a^2.0.0"), + root: rootNode + ) XCTAssertEqual(i2.terms.count, 1) let a2 = i2.terms.first XCTAssertEqual(a2?.requirement, v2Range) } func testSolutionPositive() { - let s1 = PartialSolution(assignments:[ + let s1 = PartialSolution(assignments: [ .derivation("a^1.5.0", cause: _cause, decisionLevel: 0), .derivation("b@2.0.0", cause: _cause, decisionLevel: 0), - .derivation("a^1.0.0", cause: _cause, decisionLevel: 0) + .derivation("a^1.0.0", cause: _cause, decisionLevel: 0), ]) let a1 = s1._positive.first { $0.key.package.identity == PackageIdentity("a") }?.value XCTAssertEqual(a1?.requirement, v1_5Range) @@ -221,7 +237,7 @@ final class PubGrubTests: XCTestCase { let s2 = PartialSolution(assignments: [ .derivation("¬a^1.5.0", cause: _cause, decisionLevel: 0), - .derivation("a^1.0.0", cause: _cause, decisionLevel: 0) + .derivation("a^1.0.0", cause: _cause, decisionLevel: 0), ]) let a2 = s2._positive.first { $0.key.package.identity == PackageIdentity("a") }?.value XCTAssertEqual(a2?.requirement, .range(v1.. version -> version @@ -957,16 +1136,19 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "foo": (.versionSet(v1Range), .specific(["foo"])), - "bar": (.versionSet(v1Range), .specific(["bar"])) + "bar": (.versionSet(v1Range), .specific(["bar"])), ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .version(v1_1)), - ("bar", .version(v1_1)), - ("config", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("foo", .version(v1_1)), + ("bar", .version(v1_1)), + ("config", .version(v1_1)), + ] + ) } // root -> version -> version @@ -974,22 +1156,25 @@ final class PubGrubTests: XCTestCase { func testHappyPath2() async throws { try builder.serve("foo", at: v1_1, with: ["foo": ["config": (.versionSet(v1Range), .specific(["config"]))]]) try builder.serve("bar", at: .unversioned, with: ["bar": ["config": (.versionSet(v1_1Range), .specific(["config"]))]]) - try builder.serve("config", at: v1) - try builder.serve("config", at: v1_1) + try builder.serve("config", at: v1) + try builder.serve("config", at: v1_1) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "foo": (.versionSet(v1Range), .specific(["foo"])), - "bar": (.unversioned, .specific(["bar"])) + "bar": (.unversioned, .specific(["bar"])), ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .version(v1_1)), - ("bar", .unversioned), - ("config", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("foo", .version(v1_1)), + ("bar", .unversioned), + ("config", .version(v1_1)), + ] + ) } // root -> version -> version @@ -1004,17 +1189,20 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "foo": (.versionSet(v1Range), .specific(["foo"])), - "bar": (.unversioned, .specific(["bar"])) + "bar": (.unversioned, .specific(["bar"])), ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .version(v1_1)), - ("bar", .unversioned), - ("baz", .unversioned), - ("config", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("foo", .version(v1_1)), + ("bar", .unversioned), + ("baz", .unversioned), + ("config", .version(v1_1)), + ] + ) } // root -> version @@ -1027,15 +1215,18 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.versionSet(v1Range), .specific(["foo"])) + "foo": (.versionSet(v1Range), .specific(["foo"])), ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .version(v1_1)), - ("config", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("foo", .version(v1_1)), + ("config", .version(v1_1)), + ] + ) } // root -> version @@ -1048,15 +1239,18 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) + "foo": (.unversioned, .specific(["foo"])), ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .unversioned), - ("config", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("foo", .unversioned), + ("config", .version(v1_1)), + ] + ) } // root -> version @@ -1070,27 +1264,35 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) + "foo": (.unversioned, .specific(["foo"])), ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .unversioned), - ("bar", .unversioned), - ("config", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("foo", .unversioned), + ("bar", .unversioned), + ("config", .version(v1_1)), + ] + ) } // top level package -> version // top level package -> version -> version func testHappyPath7() async throws { let package = PackageReference.root(identity: .plain("package"), path: .root) - try builder.serve(package, at: .unversioned, with: [ - "module": [ - "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.versionSet(v1Range), .specific(["foo"])) - ]]) + try builder.serve( + package, + at: .unversioned, + with: [ + "module": [ + "config": (.versionSet(v1Range), .specific(["config"])), + "foo": (.versionSet(v1Range), .specific(["foo"])), + ] + ] + ) try builder.serve("foo", at: v1_1, with: ["foo": ["config": (.versionSet(v1_1Range), .specific(["config"]))]]) try builder.serve("config", at: v1) try builder.serve("config", at: v1_1) @@ -1102,23 +1304,30 @@ final class PubGrubTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("package", .unversioned), - ("foo", .version(v1_1)), - ("config", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("package", .unversioned), + ("foo", .version(v1_1)), + ("config", .version(v1_1)), + ] + ) } - // top level package -> version // top level package -> non-versioned -> version func testHappyPath8() async throws { let package = PackageReference.root(identity: .plain("package"), path: .root) - try builder.serve(package, at: .unversioned, with: [ - "module": [ - "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) - ]]) + try builder.serve( + package, + at: .unversioned, + with: [ + "module": [ + "config": (.versionSet(v1Range), .specific(["config"])), + "foo": (.unversioned, .specific(["foo"])), + ] + ] + ) try builder.serve("foo", at: .unversioned, with: ["foo": ["config": (.versionSet(v1_1Range), .specific(["config"]))]]) try builder.serve("config", at: v1) try builder.serve("config", at: v1_1) @@ -1130,22 +1339,30 @@ final class PubGrubTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("package", .unversioned), - ("foo", .unversioned), - ("config", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("package", .unversioned), + ("foo", .unversioned), + ("config", .version(v1_1)), + ] + ) } // top level package -> version // top level package -> non-versioned -> non-versioned -> version func testHappyPath9() async throws { let package = PackageReference.root(identity: .plain("package"), path: .root) - try builder.serve(package, at: .unversioned, with: [ - "module": [ - "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) - ]]) + try builder.serve( + package, + at: .unversioned, + with: [ + "module": [ + "config": (.versionSet(v1Range), .specific(["config"])), + "foo": (.unversioned, .specific(["foo"])), + ] + ] + ) try builder.serve("foo", at: .unversioned, with: ["foo": ["bar": (.unversioned, .specific(["bar"]))]]) try builder.serve("bar", at: .unversioned, with: ["bar": ["baz": (.unversioned, .specific(["baz"]))]]) try builder.serve("baz", at: .unversioned, with: ["baz": ["config": (.versionSet(v1_1Range), .specific(["config"]))]]) @@ -1159,23 +1376,31 @@ final class PubGrubTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("package", .unversioned), - ("foo", .unversioned), - ("bar", .unversioned), - ("baz", .unversioned), - ("config", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("package", .unversioned), + ("foo", .unversioned), + ("bar", .unversioned), + ("baz", .unversioned), + ("config", .version(v1_1)), + ] + ) } // top level package -> beta version // beta version -> version func testHappyPath10() async throws { let package = PackageReference.root(identity: .plain("package"), path: .root) - try builder.serve(package, at: .unversioned, with: [ - "module": [ - "foo": (.versionSet(.range("1.0.0-alpha" ..< "2.0.0")), .specific(["foo"])) - ]]) + try builder.serve( + package, + at: .unversioned, + with: [ + "module": [ + "foo": (.versionSet(.range("1.0.0-alpha"..<"2.0.0")), .specific(["foo"])) + ] + ] + ) try builder.serve("foo", at: "1.0.0-alpha.1", with: ["foo": ["bar": (.versionSet(v1Range), .specific(["bar"]))]]) try builder.serve("foo", at: "1.0.0-alpha.2", with: ["foo": ["bar": (.versionSet(v1Range), .specific(["bar"]))]]) try builder.serve("foo", at: "1.0.0-beta.1", with: ["foo": ["bar": (.versionSet(v1Range), .specific(["bar"]))]]) @@ -1192,11 +1417,14 @@ final class PubGrubTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("package", .unversioned), - ("foo", .version("1.0.0-beta.3")), - ("bar", .version(v1_5)) - ]) + AssertResult( + result, + [ + ("package", .unversioned), + ("foo", .version("1.0.0-beta.3")), + ("bar", .version(v1_5)), + ] + ) } func testResolutionWithSimpleBranchBasedDependency() async throws { @@ -1206,14 +1434,17 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "foo": (.revision("master"), .specific(["foo"])), - "bar": (.versionSet(v1Range), .specific(["bar"])) + "bar": (.versionSet(v1Range), .specific(["bar"])), ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .revision("master")), - ("bar", .version(v1)) - ]) + AssertResult( + result, + [ + ("foo", .revision("master")), + ("bar", .version(v1)), + ] + ) } func testResolutionWithSimpleBranchBasedDependency2() async throws { @@ -1222,14 +1453,17 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "foo": (.revision("master"), .specific(["foo"])), + "foo": (.revision("master"), .specific(["foo"])) ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .revision("master")), - ("bar", .version(v1)) - ]) + AssertResult( + result, + [ + ("foo", .revision("master")), + ("bar", .version(v1)), + ] + ) } func testResolutionWithOverridingBranchBasedDependency() async throws { @@ -1244,10 +1478,13 @@ final class PubGrubTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .revision("master")), - ("bar", .version(v1)) - ]) + AssertResult( + result, + [ + ("foo", .revision("master")), + ("bar", .version(v1)), + ] + ) } func testResolutionWithOverridingBranchBasedDependency2() async throws { @@ -1261,10 +1498,13 @@ final class PubGrubTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .revision("master")), - ("bar", .version(v1)) - ]) + AssertResult( + result, + [ + ("foo", .revision("master")), + ("bar", .version(v1)), + ] + ) } func testResolutionWithOverridingBranchBasedDependency3() async throws { @@ -1282,11 +1522,14 @@ final class PubGrubTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .revision("master")), - ("bar", .revision("master")), - ("baz", .revision("master")), - ]) + AssertResult( + result, + [ + ("foo", .revision("master")), + ("bar", .revision("master")), + ("baz", .revision("master")), + ] + ) } func testResolutionWithUnavailableRevision() async throws { @@ -1313,21 +1556,32 @@ final class PubGrubTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .revision("master")), - ("bar", .revision("master")), - ]) + AssertResult( + result, + [ + ("foo", .revision("master")), + ("bar", .revision("master")), + ] + ) } func testBranchOverriding3() async throws { try builder.serve("swift-nio", at: v1) try builder.serve("swift-nio", at: .revision("master")) - try builder.serve("swift-nio-ssl", at: .revision("master"), with: [ - "swift-nio-ssl": ["swift-nio": (.versionSet(v2Range), .specific(["swift-nio"]))], - ]) - try builder.serve("foo", at: "1.0.0", with: [ - "foo": ["swift-nio": (.versionSet(v1Range), .specific(["swift-nio"]))], - ]) + try builder.serve( + "swift-nio-ssl", + at: .revision("master"), + with: [ + "swift-nio-ssl": ["swift-nio": (.versionSet(v2Range), .specific(["swift-nio"]))] + ] + ) + try builder.serve( + "foo", + at: "1.0.0", + with: [ + "foo": ["swift-nio": (.versionSet(v1Range), .specific(["swift-nio"]))] + ] + ) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ @@ -1337,34 +1591,53 @@ final class PubGrubTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("swift-nio-ssl", .revision("master")), - ("swift-nio", .revision("master")), - ("foo", .version(v1)) - ]) + AssertResult( + result, + [ + ("swift-nio-ssl", .revision("master")), + ("swift-nio", .revision("master")), + ("foo", .version(v1)), + ] + ) } func testBranchOverriding4() async throws { try builder.serve("swift-nio", at: v1) try builder.serve("swift-nio", at: .revision("master")) - try builder.serve("swift-nio-ssl", at: .revision("master"), with: [ - "swift-nio-ssl": ["swift-nio": (.versionSet(v2Range), .specific(["swift-nio"]))], - ]) - try builder.serve("nio-postgres", at: .revision("master"), with: [ - "nio-postgres": [ - "swift-nio": (.revision("master"), .specific(["swift-nio"])), - "swift-nio-ssl": (.revision("master"), .specific(["swift-nio-ssl"])), + try builder.serve( + "swift-nio-ssl", + at: .revision("master"), + with: [ + "swift-nio-ssl": ["swift-nio": (.versionSet(v2Range), .specific(["swift-nio"]))] ] - ]) - try builder.serve("http-client", at: v1, with: [ - "http-client": [ - "swift-nio": (.versionSet(v1Range), .specific(["swift-nio"])), - "boring-ssl": (.versionSet(v1Range), .specific(["boring-ssl"])), + ) + try builder.serve( + "nio-postgres", + at: .revision("master"), + with: [ + "nio-postgres": [ + "swift-nio": (.revision("master"), .specific(["swift-nio"])), + "swift-nio-ssl": (.revision("master"), .specific(["swift-nio-ssl"])), + ] ] - ]) - try builder.serve("boring-ssl", at: v1, with: [ - "boring-ssl": ["swift-nio": (.versionSet(v1Range), .specific(["swift-nio"]))], - ]) + ) + try builder.serve( + "http-client", + at: v1, + with: [ + "http-client": [ + "swift-nio": (.versionSet(v1Range), .specific(["swift-nio"])), + "boring-ssl": (.versionSet(v1Range), .specific(["boring-ssl"])), + ] + ] + ) + try builder.serve( + "boring-ssl", + at: v1, + with: [ + "boring-ssl": ["swift-nio": (.versionSet(v1Range), .specific(["swift-nio"]))] + ] + ) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ @@ -1374,29 +1647,39 @@ final class PubGrubTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("swift-nio-ssl", .revision("master")), - ("swift-nio", .revision("master")), - ("nio-postgres", .revision("master")), - ("http-client", .version(v1)), - ("boring-ssl", .version(v1)), - ]) + AssertResult( + result, + [ + ("swift-nio-ssl", .revision("master")), + ("swift-nio", .revision("master")), + ("nio-postgres", .revision("master")), + ("http-client", .version(v1)), + ("boring-ssl", .version(v1)), + ] + ) } func testNonVersionDependencyInVersionDependency2() async throws { - try builder.serve("foo", at: v1_1, with: [ - "foo": ["bar": (.revision("master"), .specific(["bar"]))] - ]) + try builder.serve( + "foo", + at: v1_1, + with: [ + "foo": ["bar": (.revision("master"), .specific(["bar"]))] + ] + ) try builder.serve("foo", at: v1) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "foo": (.versionSet(v1Range), .specific(["foo"])), + "foo": (.versionSet(v1Range), .specific(["foo"])) ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .version(v1)), - ]) + AssertResult( + result, + [ + ("foo", .version(v1)) + ] + ) } func testTrivialResolvedPackagesStore() async throws { @@ -1407,7 +1690,7 @@ final class PubGrubTests: XCTestCase { try builder.serve("b", at: v2) let dependencies = try builder.create(dependencies: [ - "a": (.versionSet(v1Range), .specific(["a"])), + "a": (.versionSet(v1Range), .specific(["a"])) ]) let resolvedPackagesStore = try builder.create(resolvedPackages: [ @@ -1422,10 +1705,13 @@ final class PubGrubTests: XCTestCase { let aIncompat = result.state.positiveIncompatibilities(for: .product("a", package: try builder.reference(for: "a")))![0] XCTAssertEqual(aIncompat.terms[0].requirement, .exact("1.0.0")) - AssertResult(Result.success(result.bindings), [ - ("a", .version(v1)), - ("b", .version(v1)) - ]) + AssertResult( + Result.success(result.bindings), + [ + ("a", .version(v1)), + ("b", .version(v1)), + ] + ) } func testPartialResolvedPackages() async throws { @@ -1452,11 +1738,14 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create(resolvedPackages: resolvedPackagesStore.resolvedPackages) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .version(v1)), - ("b", .version(v1_1)), - ("c", .version(v1)) - ]) + AssertResult( + result, + [ + ("a", .version(v1)), + ("b", .version(v1_1)), + ("c", .version(v1)), + ] + ) } func testMissingResolvedPackage() async throws { @@ -1468,7 +1757,7 @@ final class PubGrubTests: XCTestCase { try builder.serve("b", at: v1_1) let dependencies = try builder.create(dependencies: [ - "a": (.versionSet(v1Range), .specific(["a"])), + "a": (.versionSet(v1Range), .specific(["a"])) ]) // Here c is pinned to v1.1, but it is no longer available, so the resolver should fall back @@ -1481,10 +1770,13 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create(resolvedPackages: resolvedPackagesStore.resolvedPackages) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .version(v1)), - ("b", .version(v1_1)), - ]) + AssertResult( + result, + [ + ("a", .version(v1)), + ("b", .version(v1_1)), + ] + ) } func testBranchBasedResolvedPackage() async throws { @@ -1506,10 +1798,13 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create(resolvedPackages: resolvedPackagesStore.resolvedPackages) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .revision("develop-sha-1", branch: "develop")), - ("b", .revision("master-sha-2", branch: "master")), - ]) + AssertResult( + result, + [ + ("a", .revision("develop-sha-1", branch: "develop")), + ("b", .revision("master-sha-2", branch: "master")), + ] + ) } func testIncompatibleToolsVersion2() async throws { @@ -1518,38 +1813,53 @@ final class PubGrubTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "a": (.versionSet(v1Range), .specific(["a"])), + "a": (.versionSet(v1Range), .specific(["a"])) ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .version(v1)), - ]) + AssertResult( + result, + [ + ("a", .version(v1)) + ] + ) } func testUnreachableProductsSkipped() async throws { #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION #else - try XCTSkipIf(true) + try XCTSkipIf(true) #endif - try builder.serve("root", at: .unversioned, with: [ - "root": ["immediate": (.versionSet(v1Range), .specific(["ImmediateUsed"]))] - ]) - try builder.serve("immediate", at: v1, with: [ - "ImmediateUsed": ["transitive": (.versionSet(v1Range), .specific(["TransitiveUsed"]))], - "ImmediateUnused": [ - "transitive": (.versionSet(v1Range), .specific(["TransitiveUnused"])), - "nonexistent": (.versionSet(v1Range), .specific(["Nonexistent"])) + try builder.serve( + "root", + at: .unversioned, + with: [ + "root": ["immediate": (.versionSet(v1Range), .specific(["ImmediateUsed"]))] ] - ]) - try builder.serve("transitive", at: v1, with: [ - "TransitiveUsed": [:], - "TransitiveUnused": [ - "nonexistent": (.versionSet(v1Range), .specific(["Nonexistent"])) + ) + try builder.serve( + "immediate", + at: v1, + with: [ + "ImmediateUsed": ["transitive": (.versionSet(v1Range), .specific(["TransitiveUsed"]))], + "ImmediateUnused": [ + "transitive": (.versionSet(v1Range), .specific(["TransitiveUnused"])), + "nonexistent": (.versionSet(v1Range), .specific(["Nonexistent"])), + ], ] - ]) + ) + try builder.serve( + "transitive", + at: v1, + with: [ + "TransitiveUsed": [:], + "TransitiveUnused": [ + "nonexistent": (.versionSet(v1Range), .specific(["Nonexistent"])) + ], + ] + ) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ @@ -1557,11 +1867,14 @@ final class PubGrubTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("root", .unversioned), - ("immediate", .version(v1)), - ("transitive", .version(v1)) - ]) + AssertResult( + result, + [ + ("root", .unversioned), + ("immediate", .version(v1)), + ("transitive", .version(v1)), + ] + ) } func testDelegate() async throws { @@ -1617,10 +1930,13 @@ final class PubGrubTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .version("1.1.0")), - ("bar", .version("2.0.1")), - ]) + AssertResult( + result, + [ + ("foo", .version("1.1.0")), + ("bar", .version("2.0.1")), + ] + ) XCTAssertMatch(delegate.events, ["willResolve 'foo'"]) XCTAssertMatch(delegate.events, ["didResolve 'foo' at '1.1.0'"]) @@ -1634,15 +1950,20 @@ final class PubGrubTests: XCTestCase { underlying: try MockPackageContainer( name: "Package", dependenciesByProductFilter: [ - .specific(["FilterA"]): [( - container: "DependencyA", - versionRequirement: .exact(Version(1, 0, 0)) - )], - .specific(["FilterB"]): [( - container: "DependencyB", - versionRequirement: .exact(Version(1, 0, 0)) - )] - ]), + .specific(["FilterA"]): [ + ( + container: "DependencyA", + versionRequirement: .exact(Version(1, 0, 0)) + ) + ], + .specific(["FilterB"]): [ + ( + container: "DependencyB", + versionRequirement: .exact(Version(1, 0, 0)) + ) + ], + ] + ), resolvedPackages: ResolvedPackagesStore.ResolvedPackages() ) let rootLocation = AbsolutePath("/Root") @@ -1668,29 +1989,33 @@ final class PubGrubTests: XCTestCase { Incompatibility( terms: [ Term( - node: .product("FilterA", package: other), requirement: .exact(Version(1, 0, 0)), + node: .product("FilterA", package: other), + requirement: .exact(Version(1, 0, 0)), isPositive: true ), Term( - node: .product("FilterA", package: dependencyA), requirement: .exact(Version(1, 0, 0)), + node: .product("FilterA", package: dependencyA), + requirement: .exact(Version(1, 0, 0)), isPositive: false - ) + ), ], cause: .dependency(node: .product("FilterA", package: other)) ), Incompatibility( terms: [ Term( - node: .product("FilterA", package: other), requirement: .exact(Version(1, 0, 0)), + node: .product("FilterA", package: other), + requirement: .exact(Version(1, 0, 0)), isPositive: true ), Term( - node: .empty(package: other), requirement: .exact(Version(1, 0, 0)), + node: .empty(package: other), + requirement: .exact(Version(1, 0, 0)), isPositive: false ), ], cause: .dependency(node: .product("FilterA", package: other)) - ) + ), ] ) let result2 = try await container.incompatibilites( @@ -1708,29 +2033,33 @@ final class PubGrubTests: XCTestCase { Incompatibility( terms: [ Term( - node: .product("FilterB", package: other), requirement: .exact(Version(1, 0, 0)), + node: .product("FilterB", package: other), + requirement: .exact(Version(1, 0, 0)), isPositive: true ), Term( - node: .product("FilterB", package: dependencyB), requirement: .exact(Version(1, 0, 0)), + node: .product("FilterB", package: dependencyB), + requirement: .exact(Version(1, 0, 0)), isPositive: false - ) + ), ], cause: .dependency(node: .product("FilterB", package: other)) ), Incompatibility( terms: [ Term( - node: .product("FilterB", package: other), requirement: .exact(Version(1, 0, 0)), + node: .product("FilterB", package: other), + requirement: .exact(Version(1, 0, 0)), isPositive: true ), Term( - node: .empty(package: other), requirement: .exact(Version(1, 0, 0)), + node: .empty(package: other), + requirement: .exact(Version(1, 0, 0)), isPositive: false ), ], cause: .dependency(node: .product("FilterB", package: other)) - ) + ), ] ) } @@ -1738,20 +2067,28 @@ final class PubGrubTests: XCTestCase { final class PubGrubTestsBasicGraphs: XCTestCase { func testSimple1() async throws { - try builder.serve("a", at: v1, with: [ - "a": [ - "aa": (.versionSet(.exact("1.0.0")), .specific(["aa"])), - "ab": (.versionSet(.exact("1.0.0")), .specific(["ab"])), + try builder.serve( + "a", + at: v1, + with: [ + "a": [ + "aa": (.versionSet(.exact("1.0.0")), .specific(["aa"])), + "ab": (.versionSet(.exact("1.0.0")), .specific(["ab"])), + ] ] - ]) + ) try builder.serve("aa", at: v1) try builder.serve("ab", at: v1) - try builder.serve("b", at: v1, with: [ - "b": [ - "ba": (.versionSet(.exact("1.0.0")), .specific(["ba"])), - "bb": (.versionSet(.exact("1.0.0")), .specific(["bb"])), + try builder.serve( + "b", + at: v1, + with: [ + "b": [ + "ba": (.versionSet(.exact("1.0.0")), .specific(["ba"])), + "bb": (.versionSet(.exact("1.0.0")), .specific(["bb"])), + ] ] - ]) + ) try builder.serve("ba", at: v1) try builder.serve("bb", at: v1) @@ -1762,23 +2099,34 @@ final class PubGrubTestsBasicGraphs: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .version(v1)), - ("aa", .version(v1)), - ("ab", .version(v1)), - ("b", .version(v1)), - ("ba", .version(v1)), - ("bb", .version(v1)), - ]) + AssertResult( + result, + [ + ("a", .version(v1)), + ("aa", .version(v1)), + ("ab", .version(v1)), + ("b", .version(v1)), + ("ba", .version(v1)), + ("bb", .version(v1)), + ] + ) } func testSharedDependency1() async throws { - try builder.serve("a", at: v1, with: [ - "a": ["shared": (.versionSet(.range("2.0.0"..<"4.0.0")), .specific(["shared"]))], - ]) - try builder.serve("b", at: v1, with: [ - "b": ["shared": (.versionSet(.range("3.0.0"..<"5.0.0")), .specific(["shared"]))], - ]) + try builder.serve( + "a", + at: v1, + with: [ + "a": ["shared": (.versionSet(.range("2.0.0"..<"4.0.0")), .specific(["shared"]))] + ] + ) + try builder.serve( + "b", + at: v1, + with: [ + "b": ["shared": (.versionSet(.range("3.0.0"..<"5.0.0")), .specific(["shared"]))] + ] + ) try builder.serve("shared", at: "2.0.0") try builder.serve("shared", at: "3.0.0") try builder.serve("shared", at: "3.6.9") @@ -1792,27 +2140,46 @@ final class PubGrubTestsBasicGraphs: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .version(v1)), - ("b", .version(v1)), - ("shared", .version("3.6.9")), - ]) + AssertResult( + result, + [ + ("a", .version(v1)), + ("b", .version(v1)), + ("shared", .version("3.6.9")), + ] + ) } func testSharedDependency2() async throws { try builder.serve("foo", at: "1.0.0") - try builder.serve("foo", at: "1.0.1", with: [ - "foo": ["bang": (.versionSet(.exact("1.0.0")), .specific(["bang"]))], - ]) - try builder.serve("foo", at: "1.0.2", with: [ - "foo": ["whoop": (.versionSet(.exact("1.0.0")), .specific(["whoop"]))], - ]) - try builder.serve("foo", at: "1.0.3", with: [ - "foo": ["zoop": (.versionSet(.exact("1.0.0")), .specific(["zoop"]))], - ]) - try builder.serve("bar", at: "1.0.0", with: [ - "bar": ["foo": (.versionSet(.range("0.0.0"..<"1.0.2")), .specific(["foo"]))], - ]) + try builder.serve( + "foo", + at: "1.0.1", + with: [ + "foo": ["bang": (.versionSet(.exact("1.0.0")), .specific(["bang"]))] + ] + ) + try builder.serve( + "foo", + at: "1.0.2", + with: [ + "foo": ["whoop": (.versionSet(.exact("1.0.0")), .specific(["whoop"]))] + ] + ) + try builder.serve( + "foo", + at: "1.0.3", + with: [ + "foo": ["zoop": (.versionSet(.exact("1.0.0")), .specific(["zoop"]))] + ] + ) + try builder.serve( + "bar", + at: "1.0.0", + with: [ + "bar": ["foo": (.versionSet(.range("0.0.0"..<"1.0.2")), .specific(["foo"]))] + ] + ) try builder.serve("bang", at: "1.0.0") try builder.serve("whoop", at: "1.0.0") try builder.serve("zoop", at: "1.0.0") @@ -1824,23 +2191,34 @@ final class PubGrubTestsBasicGraphs: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .version("1.0.1")), - ("bar", .version(v1)), - ("bang", .version(v1)), - ]) + AssertResult( + result, + [ + ("foo", .version("1.0.1")), + ("bar", .version(v1)), + ("bang", .version(v1)), + ] + ) } func testFallbacksToOlderVersion() async throws { try builder.serve("foo", at: "1.0.0") try builder.serve("foo", at: "2.0.0") try builder.serve("bar", at: "1.0.0") - try builder.serve("bar", at: "2.0.0", with: [ - "bar": ["baz": (.versionSet(.exact("1.0.0")), .specific(["baz"]))], - ]) - try builder.serve("baz", at: "1.0.0", with: [ - "baz": ["foo": (.versionSet(.exact("2.0.0")), .specific(["foo"]))], - ]) + try builder.serve( + "bar", + at: "2.0.0", + with: [ + "bar": ["baz": (.versionSet(.exact("1.0.0")), .specific(["baz"]))] + ] + ) + try builder.serve( + "baz", + at: "1.0.0", + with: [ + "baz": ["foo": (.versionSet(.exact("2.0.0")), .specific(["foo"]))] + ] + ) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ @@ -1849,10 +2227,13 @@ final class PubGrubTestsBasicGraphs: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .version(v1)), - ("bar", .version(v1)), - ]) + AssertResult( + result, + [ + ("foo", .version(v1)), + ("bar", .version(v1)), + ] + ) } } @@ -1863,13 +2244,16 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "package": (.versionSet(v2Range), .specific(["package"])), + "package": (.versionSet(v2Range), .specific(["package"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because no versions of 'package' match the requirement 2.0.0..<3.0.0 and root depends on 'package' 2.0.0..<3.0.0. - """) + """ + ) } func testResolutionNonExistentVersion() async throws { @@ -1881,9 +2265,12 @@ final class PubGrubDiagnosticsTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because no versions of 'package' match the requirement 1.0.0 and root depends on 'package' 1.0.0. - """) + """ + ) } func testResolutionNonExistentBetaVersion() async throws { @@ -1891,19 +2278,26 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "package": (.versionSet(.range("1.0.0-beta" ..< "2.0.0")), .specific(["package"])), + "package": (.versionSet(.range("1.0.0-beta"..<"2.0.0")), .specific(["package"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because no versions of 'package' match the requirement 1.0.0-beta..<2.0.0 and root depends on 'package' 1.0.0-beta..<2.0.0. - """) + """ + ) } func testResolutionNonExistentTransitiveVersion() async throws { - try builder.serve("package", at: v1_5, with: [ - "package": ["foo": (.versionSet(v1Range), .specific(["foo"]))] - ]) + try builder.serve( + "package", + at: v1_5, + with: [ + "package": ["foo": (.versionSet(v1Range), .specific(["foo"]))] + ] + ) try builder.serve("foo", at: "0.0.1") let resolver = builder.create() @@ -1912,16 +2306,23 @@ final class PubGrubDiagnosticsTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because no versions of 'foo' match the requirement 1.0.0..<2.0.0 and root depends on 'package' 1.0.0..<2.0.0. 'package' practically depends on 'foo' 1.0.0..<2.0.0 because no versions of 'package' match the requirement {1.0.0..<1.5.0, 1.5.1..<2.0.0} and 'package' 1.5.0 depends on 'foo' 1.0.0..<2.0.0. - """) + """ + ) } func testResolutionNonExistentTransitiveBetaVersion() async throws { - try builder.serve("package", at: v1_5, with: [ - "package": ["foo": (.versionSet(.range("1.0.0-beta" ..< "2.0.0")), .specific(["foo"]))] - ]) + try builder.serve( + "package", + at: v1_5, + with: [ + "package": ["foo": (.versionSet(.range("1.0.0-beta"..<"2.0.0")), .specific(["foo"]))] + ] + ) try builder.serve("foo", at: "0.0.1") let resolver = builder.create() @@ -1930,28 +2331,38 @@ final class PubGrubDiagnosticsTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because no versions of 'foo' match the requirement 1.0.0-beta..<2.0.0 and root depends on 'package' 1.0.0..<2.0.0. 'package' practically depends on 'foo' 1.0.0-beta..<2.0.0 because no versions of 'package' match the requirement {1.0.0..<1.5.0, 1.5.1..<2.0.0} and 'package' 1.5.0 depends on 'foo' 1.0.0-beta..<2.0.0. - """) + """ + ) } func testResolutionBetaVersionNonExistentTransitiveVersion() async throws { - try builder.serve("package", at: "1.0.0-beta.1", with: [ - "package": ["foo": (.versionSet(v1Range), .specific(["foo"]))] - ]) + try builder.serve( + "package", + at: "1.0.0-beta.1", + with: [ + "package": ["foo": (.versionSet(v1Range), .specific(["foo"]))] + ] + ) try builder.serve("foo", at: "0.0.1") let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "package": (.versionSet(.range("1.0.0-beta" ..< "2.0.0")), .specific(["package"])), + "package": (.versionSet(.range("1.0.0-beta"..<"2.0.0")), .specific(["package"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because no versions of 'foo' match the requirement 1.0.0..<2.0.0 and root depends on 'package' 1.0.0-beta..<2.0.0. 'package' practically depends on 'foo' 1.0.0..<2.0.0 because no versions of 'package' match the requirement {1.0.0-beta..<1.0.0-beta.1, 1.0.0-beta.1.0..<2.0.0} and 'package' 1.0.0-beta.1 depends on 'foo' 1.0.0..<2.0.0. - """) + """ + ) } func testResolutionLinearErrorReporting() async throws { @@ -1970,27 +2381,38 @@ final class PubGrubDiagnosticsTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'foo' 1.0.0..<2.0.0 and root depends on 'baz' 1.0.0..<2.0.0. 'foo' >= 1.0.0 practically depends on 'baz' 3.0.0..<4.0.0. 'bar' >= 2.0.0 practically depends on 'baz' 3.0.0..<4.0.0 because 'bar' 2.0.0 depends on 'baz' 3.0.0..<4.0.0 and no versions of 'bar' match the requirement 2.0.1..<3.0.0. 'foo' >= 1.0.0 practically depends on 'bar' 2.0.0..<3.0.0 because 'foo' 1.0.0 depends on 'bar' 2.0.0..<3.0.0 and no versions of 'foo' match the requirement 1.0.1..<2.0.0. - """) + """ + ) } func testResolutionBranchingErrorReporting() async throws { - try builder.serve("foo", at: v1, with: [ - "foo": [ - "a": (.versionSet(v1Range), .specific(["a"])), - "b": (.versionSet(v1Range), .specific(["b"])) + try builder.serve( + "foo", + at: v1, + with: [ + "foo": [ + "a": (.versionSet(v1Range), .specific(["a"])), + "b": (.versionSet(v1Range), .specific(["b"])), + ] ] - ]) - try builder.serve("foo", at: v1_1, with: [ - "foo": [ - "x": (.versionSet(v1Range), .specific(["x"])), - "y": (.versionSet(v1Range), .specific(["y"])) + ) + try builder.serve( + "foo", + at: v1_1, + with: [ + "foo": [ + "x": (.versionSet(v1Range), .specific(["x"])), + "y": (.versionSet(v1Range), .specific(["y"])), + ] ] - ]) + ) try builder.serve("a", at: v1, with: ["a": ["b": (.versionSet(v2Range), .specific(["b"]))]]) try builder.serve("b", at: v1) try builder.serve("b", at: v2) @@ -2000,13 +2422,15 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "foo": (.versionSet(v1Range), .specific(["foo"])), + "foo": (.versionSet(v1Range), .specific(["foo"])) ]) let result = await resolver.solve(constraints: dependencies) print(result.errorMsg!) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'foo' 1.0.0..<2.0.0. 'foo' >= 1.0.0 cannot be used because 'foo' {1.0.0..<1.1.0, 1.1.1..<2.0.0} cannot be used (1). 'foo' 1.1.0 cannot be used because 'foo' 1.1.0 depends on 'x' 1.0.0..<2.0.0 and 'foo' 1.1.0 depends on 'y' 1.0.0..<2.0.0. @@ -2014,7 +2438,8 @@ final class PubGrubDiagnosticsTests: XCTestCase { 'foo' 1.0.0 practically depends on 'b' 2.0.0..<3.0.0 because 'foo' 1.0.0 depends on 'a' 1.0.0..<2.0.0. 'a' >= 1.0.0 practically depends on 'b' 2.0.0..<3.0.0 because 'a' 1.0.0 depends on 'b' 2.0.0..<3.0.0 and no versions of 'a' match the requirement 1.0.1..<2.0.0. (1) As a result, 'foo' {1.0.0..<1.1.0, 1.1.1..<2.0.0} cannot be used because 'foo' 1.0.0 depends on 'b' 1.0.0..<2.0.0 and no versions of 'foo' match the requirement {1.0.1..<1.1.0, 1.1.1..<2.0.0}. - """) + """ + ) } func testConflict1() async throws { @@ -2026,15 +2451,18 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "foo": (.versionSet(v1Range), .specific(["foo"])), - "bar": (.versionSet(v1Range), .specific(["bar"])) + "bar": (.versionSet(v1Range), .specific(["bar"])), ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'foo' 1.0.0..<2.0.0 and root depends on 'bar' 1.0.0..<2.0.0. 'bar' is incompatible with 'foo' because 'foo' 1.0.0 depends on 'config' 1.0.0..<2.0.0 and no versions of 'foo' match the requirement 1.0.1..<2.0.0. 'bar' >= 1.0.0 practically depends on 'config' 2.0.0..<3.0.0 because no versions of 'bar' match the requirement 1.0.1..<2.0.0 and 'bar' 1.0.0 depends on 'config' 2.0.0..<3.0.0. - """) + """ + ) } func testConflict2() async throws { @@ -2052,10 +2480,13 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver1 = builder.create() let result1 = await resolver1.solve(constraints: dependencies1) - XCTAssertEqual(result1.errorMsg, """ + XCTAssertEqual( + result1.errorMsg, + """ Dependencies could not be resolved because root depends on 'config' 2.0.0..<3.0.0 and root depends on 'foo' 1.0.0..<2.0.0. 'foo' >= 1.0.0 practically depends on 'config' 1.0.0..<2.0.0 because no versions of 'foo' match the requirement 1.0.1..<2.0.0 and 'foo' 1.0.0 depends on 'config' 1.0.0..<2.0.0. - """) + """ + ) let dependencies2 = try builder.create(dependencies: [ "foo": (.versionSet(v1Range), .specific(["foo"])), @@ -2065,10 +2496,13 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver2 = builder.create() let result2 = await resolver2.solve(constraints: dependencies2) - XCTAssertEqual(result2.errorMsg, """ + XCTAssertEqual( + result2.errorMsg, + """ Dependencies could not be resolved because root depends on 'foo' 1.0.0..<2.0.0 and root depends on 'config' 2.0.0..<3.0.0. 'foo' >= 1.0.0 practically depends on 'config' 1.0.0..<2.0.0 because 'foo' 1.0.0 depends on 'config' 1.0.0..<2.0.0 and no versions of 'foo' match the requirement 1.0.1..<2.0.0. - """) + """ + ) } func testConflict3() async throws { @@ -2082,18 +2516,29 @@ final class PubGrubDiagnosticsTests: XCTestCase { ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because no versions of 'config' match the requirement 2.0.0..<3.0.0 and root depends on 'config' 2.0.0..<3.0.0. - """) + """ + ) } func testConflict4() async throws { - try builder.serve("foo", at: v1, with: [ - "foo": ["shared": (.versionSet(.range("2.0.0"..<"3.0.0")), .specific(["shared"]))], - ]) - try builder.serve("bar", at: v1, with: [ - "bar": ["shared": (.versionSet(.range("2.9.0"..<"4.0.0")), .specific(["shared"]))], - ]) + try builder.serve( + "foo", + at: v1, + with: [ + "foo": ["shared": (.versionSet(.range("2.0.0"..<"3.0.0")), .specific(["shared"]))] + ] + ) + try builder.serve( + "bar", + at: v1, + with: [ + "bar": ["shared": (.versionSet(.range("2.9.0"..<"4.0.0")), .specific(["shared"]))] + ] + ) try builder.serve("shared", at: "2.5.0") try builder.serve("shared", at: "3.5.0") @@ -2105,26 +2550,45 @@ final class PubGrubDiagnosticsTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'bar' 1.0.0 and root depends on 'foo' 1.0.0. 'foo' is incompatible with 'bar' because 'foo' 1.0.0 depends on 'shared' 2.0.0..<3.0.0. 'bar' 1.0.0 practically depends on 'shared' 3.0.0..<4.0.0 because 'bar' 1.0.0 depends on 'shared' 2.9.0..<4.0.0 and no versions of 'shared' match the requirement 2.9.0..<3.0.0. - """) + """ + ) } func testConflict5() async throws { - try builder.serve("a", at: v1, with: [ - "a": ["b": (.versionSet(.exact("1.0.0")), .specific(["b"]))], - ]) - try builder.serve("a", at: "2.0.0", with: [ - "a": ["b": (.versionSet(.exact("2.0.0")), .specific(["b"]))], - ]) - try builder.serve("b", at: "1.0.0", with: [ - "b": ["a": (.versionSet(.exact("2.0.0")), .specific(["a"]))], - ]) - try builder.serve("b", at: "2.0.0", with: [ - "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))], - ]) + try builder.serve( + "a", + at: v1, + with: [ + "a": ["b": (.versionSet(.exact("1.0.0")), .specific(["b"]))] + ] + ) + try builder.serve( + "a", + at: "2.0.0", + with: [ + "a": ["b": (.versionSet(.exact("2.0.0")), .specific(["b"]))] + ] + ) + try builder.serve( + "b", + at: "1.0.0", + with: [ + "b": ["a": (.versionSet(.exact("2.0.0")), .specific(["a"]))] + ] + ) + try builder.serve( + "b", + at: "2.0.0", + with: [ + "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))] + ] + ) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ @@ -2134,13 +2598,16 @@ final class PubGrubDiagnosticsTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'a' 0.0.0..<5.0.0. 'a' cannot be used. 'a' 2.0.0 cannot be used because 'b' 2.0.0 depends on 'a' 1.0.0 and 'a' 2.0.0 depends on 'b' 2.0.0. 'a' {0.0.0..<2.0.0, 2.0.1..<5.0.0} cannot be used because 'b' 1.0.0 depends on 'a' 2.0.0. 'a' {0.0.0..<2.0.0, 2.0.1..<5.0.0} practically depends on 'b' 1.0.0 because no versions of 'a' match the requirement {0.0.0..<1.0.0, 1.0.1..<2.0.0, 2.0.1..<5.0.0} and 'a' 1.0.0 depends on 'b' 1.0.0. - """) + """ + ) } // root -> version -> version @@ -2154,16 +2621,19 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "foo": (.versionSet(v1Range), .specific(["foo"])), - "bar": (.versionSet(v1Range), .specific(["bar"])) + "bar": (.versionSet(v1Range), .specific(["bar"])), ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'foo' 1.0.0..<2.0.0 and root depends on 'bar' 1.0.0..<2.0.0. 'bar' is incompatible with 'foo' because 'foo' 1.0.0 depends on 'config' 1.0.0..<2.0.0 and no versions of 'foo' match the requirement 1.0.1..<2.0.0. 'bar' >= 1.0.0 practically depends on 'config' 2.0.0..<3.0.0 because no versions of 'bar' match the requirement 1.0.1..<2.0.0 and 'bar' 1.0.0 depends on 'config' 2.0.0..<3.0.0. - """) + """ + ) } // root -> version -> version @@ -2177,15 +2647,18 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "foo": (.versionSet(v1Range), .specific(["foo"])), - "bar": (.unversioned, .specific(["bar"])) + "bar": (.unversioned, .specific(["bar"])), ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because 'bar' depends on 'config' 2.0.0..<3.0.0 and root depends on 'foo' 1.0.0..<2.0.0. 'foo' >= 1.0.0 practically depends on 'config' 1.0.0..<2.0.0 because no versions of 'foo' match the requirement 1.0.1..<2.0.0 and 'foo' 1.0.0 depends on 'config' 1.0.0..<2.0.0. - """) + """ + ) } // root -> version -> version @@ -2200,15 +2673,18 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "foo": (.versionSet(v1Range), .specific(["foo"])), - "bar": (.unversioned, .specific(["bar"])) + "bar": (.unversioned, .specific(["bar"])), ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because 'baz' depends on 'config' 2.0.0..<3.0.0 and root depends on 'foo' 1.0.0..<2.0.0. 'foo' >= 1.0.0 practically depends on 'config' 1.0.0..<2.0.0 because no versions of 'foo' match the requirement 1.0.1..<2.0.0 and 'foo' 1.0.0 depends on 'config' 1.0.0..<2.0.0. - """) + """ + ) } // root -> version -> version @@ -2221,14 +2697,17 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "foo": (.versionSet(v1Range), .specific(["foo"])), - "bar": (.unversioned, .specific(["bar"])) + "bar": (.unversioned, .specific(["bar"])), ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because no versions of 'config' match the requirement 2.0.0..<3.0.0 and 'bar' depends on 'config' 2.0.0..<3.0.0. - """) + """ + ) } // root -> version @@ -2241,14 +2720,17 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) + "foo": (.unversioned, .specific(["foo"])), ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because 'foo' depends on 'config' 2.0.0..<3.0.0 and root depends on 'config' 1.0.0..<2.0.0. - """) + """ + ) } // root -> version @@ -2260,14 +2742,17 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) + "foo": (.unversioned, .specific(["foo"])), ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because 'foo' depends on 'config' 2.0.0..<3.0.0 and root depends on 'config' 1.0.0..<2.0.0. - """) + """ + ) } // root -> version @@ -2281,25 +2766,33 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) + "foo": (.unversioned, .specific(["foo"])), ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because 'baz' depends on 'config' 2.0.0..<3.0.0 and root depends on 'config' 1.0.0..<2.0.0. - """) + """ + ) } // top level package -> version // top level package -> version -> conflicting version func testConflict13() async throws { let package = PackageReference.root(identity: .plain("package"), path: .root) - try builder.serve(package, at: .unversioned, with: [ - "module": [ - "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.versionSet(v1Range), .specific(["foo"])) - ]]) + try builder.serve( + package, + at: .unversioned, + with: [ + "module": [ + "config": (.versionSet(v1Range), .specific(["config"])), + "foo": (.versionSet(v1Range), .specific(["foo"])), + ] + ] + ) try builder.serve("foo", at: v1, with: ["foo": ["config": (.versionSet(v2Range), .specific(["config"]))]]) try builder.serve("config", at: v1) try builder.serve("config", at: v2) @@ -2311,21 +2804,29 @@ final class PubGrubDiagnosticsTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'config' 1.0.0..<2.0.0 and root depends on 'foo' 1.0.0..<2.0.0. 'foo' >= 1.0.0 practically depends on 'config' 2.0.0..<3.0.0 because no versions of 'foo' match the requirement 1.0.1..<2.0.0 and 'foo' 1.0.0 depends on 'config' 2.0.0..<3.0.0. - """) + """ + ) } // top level package -> version // top level package -> version -> non-existing version func testConflict14() async throws { let package = PackageReference.root(identity: .plain("package"), path: .root) - try builder.serve(package, at: .unversioned, with: [ - "module": [ - "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.versionSet(v1Range), .specific(["foo"])) - ]]) + try builder.serve( + package, + at: .unversioned, + with: [ + "module": [ + "config": (.versionSet(v1Range), .specific(["config"])), + "foo": (.versionSet(v1Range), .specific(["foo"])), + ] + ] + ) try builder.serve("foo", at: v1, with: ["foo": ["config": (.versionSet(v2Range), .specific(["config"]))]]) try builder.serve("config", at: v1) @@ -2336,21 +2837,29 @@ final class PubGrubDiagnosticsTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'config' 1.0.0..<2.0.0 and root depends on 'foo' 1.0.0..<2.0.0. 'foo' >= 1.0.0 practically depends on 'config' 2.0.0..<3.0.0 because no versions of 'foo' match the requirement 1.0.1..<2.0.0 and 'foo' 1.0.0 depends on 'config' 2.0.0..<3.0.0. - """) + """ + ) } // top level package -> version // top level package -> non-versioned -> conflicting version func testConflict15() async throws { let package = PackageReference.root(identity: .plain("package"), path: .root) - try builder.serve(package, at: .unversioned, with: [ - "module": [ - "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) - ]]) + try builder.serve( + package, + at: .unversioned, + with: [ + "module": [ + "config": (.versionSet(v1Range), .specific(["config"])), + "foo": (.unversioned, .specific(["foo"])), + ] + ] + ) try builder.serve("foo", at: .unversioned, with: ["foo": ["config": (.versionSet(v2Range), .specific(["config"]))]]) try builder.serve("config", at: v1) try builder.serve("config", at: v2) @@ -2362,20 +2871,28 @@ final class PubGrubDiagnosticsTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'config' 1.0.0..<2.0.0 and 'foo' depends on 'config' 2.0.0..<3.0.0. - """) + """ + ) } // top level package -> version // top level package -> non-versioned -> non-existing version func testConflict16() async throws { let package = PackageReference.root(identity: .plain("package"), path: .root) - try builder.serve(package, at: .unversioned, with: [ - "module": [ - "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) - ]]) + try builder.serve( + package, + at: .unversioned, + with: [ + "module": [ + "config": (.versionSet(v1Range), .specific(["config"])), + "foo": (.unversioned, .specific(["foo"])), + ] + ] + ) try builder.serve("foo", at: .unversioned, with: ["foo": ["config": (.versionSet(v2Range), .specific(["config"]))]]) try builder.serve("config", at: v1) @@ -2386,20 +2903,28 @@ final class PubGrubDiagnosticsTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'config' 1.0.0..<2.0.0 and 'foo' depends on 'config' 2.0.0..<3.0.0. - """) + """ + ) } // top level package -> version // top level package -> non-versioned -> non-versioned -> conflicting version func testConflict17() async throws { let package = PackageReference.root(identity: .plain("package"), path: .root) - try builder.serve(package, at: .unversioned, with: [ - "module": [ - "config": (.versionSet(v1Range), .specific(["config"])), - "foo": (.unversioned, .specific(["foo"])) - ]]) + try builder.serve( + package, + at: .unversioned, + with: [ + "module": [ + "config": (.versionSet(v1Range), .specific(["config"])), + "foo": (.unversioned, .specific(["foo"])), + ] + ] + ) try builder.serve("foo", at: .unversioned, with: ["foo": ["bar": (.unversioned, .specific(["bar"]))]]) try builder.serve("bar", at: .unversioned, with: ["bar": ["baz": (.unversioned, .specific(["baz"]))]]) try builder.serve("baz", at: .unversioned, with: ["baz": ["config": (.versionSet(v2Range), .specific(["config"]))]]) @@ -2413,16 +2938,23 @@ final class PubGrubDiagnosticsTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'config' 1.0.0..<2.0.0 and 'baz' depends on 'config' 2.0.0..<3.0.0. - """) + """ + ) } func testUnversioned6() async throws { try builder.serve("foo", at: .unversioned) - try builder.serve("bar", at: .revision("master"), with: [ - "bar": ["foo": (.unversioned, .specific(["foo"]))] - ]) + try builder.serve( + "bar", + at: .revision("master"), + with: [ + "bar": ["foo": (.unversioned, .specific(["foo"]))] + ] + ) let resolver = builder.create() @@ -2453,63 +2985,92 @@ final class PubGrubDiagnosticsTests: XCTestCase { } func testNonVersionDependencyInVersionDependency1() async throws { - try builder.serve("foo", at: v1_1, with: [ - "foo": ["bar": (.revision("master"), .specific(["bar"]))] - ]) + try builder.serve( + "foo", + at: v1_1, + with: [ + "foo": ["bar": (.revision("master"), .specific(["bar"]))] + ] + ) try builder.serve("bar", at: .revision("master")) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "foo": (.versionSet(v1Range), .specific(["foo"])), + "foo": (.versionSet(v1Range), .specific(["foo"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'foo' 1.0.0..<2.0.0. 'foo' cannot be used because no versions of 'foo' match the requirement {1.0.0..<1.1.0, 1.1.1..<2.0.0} and package 'foo' is required using a stable-version but 'foo' depends on an unstable-version package 'bar'. - """) + """ + ) } func testNonVersionDependencyInVersionDependency2() async throws { - try builder.serve("foo", at: v1, with: [ - "foo": ["bar": (.unversioned, .specific(["bar"]))] - ]) + try builder.serve( + "foo", + at: v1, + with: [ + "foo": ["bar": (.unversioned, .specific(["bar"]))] + ] + ) try builder.serve("bar", at: .unversioned) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "foo": (.versionSet(.exact(v1)), .specific(["foo"])), + "foo": (.versionSet(.exact(v1)), .specific(["foo"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because package 'foo' is required using a stable-version but 'foo' depends on an unstable-version package 'bar' and root depends on 'foo' 1.0.0. - """) + """ + ) } func testNonVersionDependencyInVersionDependency3() async throws { - try builder.serve("foo", at: "1.0.0-beta.1", with: [ - "foo": ["bar": (.revision("master"), .specific(["bar"]))] - ]) - try builder.serve("foo", at: "1.0.0-beta.2", with: [ - "foo": ["bar": (.revision("master"), .specific(["bar"]))] - ]) - try builder.serve("foo", at: "1.0.0-beta.3", with: [ - "foo": ["bar": (.revision("master"), .specific(["bar"]))] - ]) + try builder.serve( + "foo", + at: "1.0.0-beta.1", + with: [ + "foo": ["bar": (.revision("master"), .specific(["bar"]))] + ] + ) + try builder.serve( + "foo", + at: "1.0.0-beta.2", + with: [ + "foo": ["bar": (.revision("master"), .specific(["bar"]))] + ] + ) + try builder.serve( + "foo", + at: "1.0.0-beta.3", + with: [ + "foo": ["bar": (.revision("master"), .specific(["bar"]))] + ] + ) try builder.serve("bar", at: .revision("master")) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "foo": (.versionSet(.range("1.0.0-beta" ..< "2.0.0")), .specific(["foo"])), + "foo": (.versionSet(.range("1.0.0-beta"..<"2.0.0")), .specific(["foo"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because package 'foo' is required using a stable-version but 'foo' depends on an unstable-version package 'bar' and root depends on 'foo' 1.0.0-beta..<2.0.0. 'foo' {1.0.0-beta..<1.0.0-beta.3, 1.0.0-beta.3.0..<2.0.0} cannot be used because package 'foo' is required using a stable-version but 'foo' depends on an unstable-version package 'bar'. 'foo' {1.0.0-beta..<1.0.0-beta.2, 1.0.0-beta.2.0..<1.0.0-beta.3, 1.0.0-beta.3.0..<2.0.0} cannot be used because no versions of 'foo' match the requirement {1.0.0-beta..<1.0.0-beta.1, 1.0.0-beta.1.0..<1.0.0-beta.2, 1.0.0-beta.2.0..<1.0.0-beta.3, 1.0.0-beta.3.0..<2.0.0} and package 'foo' is required using a stable-version but 'foo' depends on an unstable-version package 'bar'. - """) + """ + ) } func testIncompatibleToolsVersion1() async throws { @@ -2517,21 +3078,28 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "a": (.versionSet(v1Range), .specific(["a"])), + "a": (.versionSet(v1Range), .specific(["a"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'a' 1.0.0..<2.0.0. 'a' >= 1.0.0 cannot be used because no versions of 'a' match the requirement 1.0.1..<2.0.0 and 'a' 1.0.0 contains incompatible tools version (\(ToolsVersion.v5)). - """) + """ + ) } func testIncompatibleToolsVersion3() async throws { - try builder.serve("a", at: v1_1, with: [ - "a": ["b": (.versionSet(v1Range), .specific(["b"]))] - ]) + try builder.serve( + "a", + at: v1_1, + with: [ + "a": ["b": (.versionSet(v1Range), .specific(["b"]))] + ] + ) try builder.serve("a", at: v1, toolsVersion: .v4) try builder.serve("b", at: v1) @@ -2545,11 +3113,14 @@ final class PubGrubDiagnosticsTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because root depends on 'a' 1.0.0..<2.0.0 and root depends on 'b' 2.0.0..<3.0.0. 'a' >= 1.0.0 practically depends on 'b' 1.0.0..<2.0.0 because 'a' 1.1.0 depends on 'b' 1.0.0..<2.0.0. 'a' {1.0.0..<1.1.0, 1.1.1..<2.0.0} cannot be used because no versions of 'a' match the requirement {1.0.1..<1.1.0, 1.1.1..<2.0.0} and 'a' 1.0.0 contains incompatible tools version (\(ToolsVersion.v4)). - """) + """ + ) } func testIncompatibleToolsVersion4() async throws { @@ -2559,14 +3130,17 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "a": (.versionSet(.range("3.2.0"..<"4.0.0")), .specific(["a"])), + "a": (.versionSet(.range("3.2.0"..<"4.0.0")), .specific(["a"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because 'a' contains incompatible tools version (\(ToolsVersion.v3)) and root depends on 'a' 3.2.0..<4.0.0. - """) + """ + ) } func testIncompatibleToolsVersion5() async throws { @@ -2576,63 +3150,93 @@ final class PubGrubDiagnosticsTests: XCTestCase { let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "a": (.versionSet(.range("3.2.0"..<"4.0.0")), .specific(["a"])), + "a": (.versionSet(.range("3.2.0"..<"4.0.0")), .specific(["a"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because 'a' contains incompatible tools version (\(ToolsVersion.v5)) and root depends on 'a' 3.2.0..<4.0.0. - """) + """ + ) } func testIncompatibleToolsVersion6() async throws { try builder.serve("a", at: "3.2.1", toolsVersion: .v5) - try builder.serve("a", at: "3.2.0", with: [ - "a": ["b": (.versionSet(v1Range), .specific(["b"]))], - ]) + try builder.serve( + "a", + at: "3.2.0", + with: [ + "a": ["b": (.versionSet(v1Range), .specific(["b"]))] + ] + ) try builder.serve("a", at: "3.2.2", toolsVersion: .v4) try builder.serve("b", at: "1.0.0", toolsVersion: .v3) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "a": (.versionSet(.range("3.2.0"..<"4.0.0")), .specific(["a"])), + "a": (.versionSet(.range("3.2.0"..<"4.0.0")), .specific(["a"])) ]) let result = await resolver.solve(constraints: dependencies) - XCTAssertEqual(result.errorMsg, """ + XCTAssertEqual( + result.errorMsg, + """ Dependencies could not be resolved because 'a' >= 3.2.1 contains incompatible tools version (\(ToolsVersion.v4)) and root depends on 'a' 3.2.0..<4.0.0. 'a' 3.2.0 cannot be used because 'a' 3.2.0 depends on 'b' 1.0.0..<2.0.0. 'b' >= 1.0.0 cannot be used because 'b' 1.0.0 contains incompatible tools version (\(ToolsVersion.v3)) and no versions of 'b' match the requirement 1.0.1..<2.0.0. - """) + """ + ) } func testProductsCannotResolveToDifferentVersions() async throws { - try builder.serve("package", at: .unversioned, with: [ - "package": [ - "intermediate_a": (.versionSet(v1Range), .specific(["Intermediate A"])), - "intermediate_b": (.versionSet(v1Range), .specific(["Intermediate B"])) + try builder.serve( + "package", + at: .unversioned, + with: [ + "package": [ + "intermediate_a": (.versionSet(v1Range), .specific(["Intermediate A"])), + "intermediate_b": (.versionSet(v1Range), .specific(["Intermediate B"])), + ] ] - ]) - try builder.serve("intermediate_a", at: v1, with: [ - "Intermediate A": [ - "transitive": (.versionSet(.exact(v1)), .specific(["Product A"])) + ) + try builder.serve( + "intermediate_a", + at: v1, + with: [ + "Intermediate A": [ + "transitive": (.versionSet(.exact(v1)), .specific(["Product A"])) + ] ] - ]) - try builder.serve("intermediate_b", at: v1, with: [ - "Intermediate B": [ - "transitive": (.versionSet(.exact(v1_1)), .specific(["Product B"])) + ) + try builder.serve( + "intermediate_b", + at: v1, + with: [ + "Intermediate B": [ + "transitive": (.versionSet(.exact(v1_1)), .specific(["Product B"])) + ] ] - ]) - try builder.serve("transitive", at: v1, with: [ - "Product A": [:], - "Product B": [:] - ]) - try builder.serve("transitive", at: v1_1, with: [ - "Product A": [:], - "Product B": [:] - ]) + ) + try builder.serve( + "transitive", + at: v1, + with: [ + "Product A": [:], + "Product B": [:], + ] + ) + try builder.serve( + "transitive", + at: v1_1, + with: [ + "Product A": [:], + "Product B": [:], + ] + ) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ @@ -2656,37 +3260,60 @@ final class PubGrubDiagnosticsTests: XCTestCase { final class PubGrubBacktrackTests: XCTestCase { func testBacktrack1() async throws { try builder.serve("a", at: v1) - try builder.serve("a", at: "2.0.0", with: [ - "a": ["b": (.versionSet(.exact("1.0.0")), .specific(["b"]))], - ]) - try builder.serve("b", at: "1.0.0", with: [ - "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))], - ]) + try builder.serve( + "a", + at: "2.0.0", + with: [ + "a": ["b": (.versionSet(.exact("1.0.0")), .specific(["b"]))] + ] + ) + try builder.serve( + "b", + at: "1.0.0", + with: [ + "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))] + ] + ) let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "a": (.versionSet(.range("1.0.0"..<"3.0.0")), .specific(["a"])), + "a": (.versionSet(.range("1.0.0"..<"3.0.0")), .specific(["a"])) ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .version(v1)), - ]) + AssertResult( + result, + [ + ("a", .version(v1)) + ] + ) } func testBacktrack2() async throws { try builder.serve("a", at: v1) - try builder.serve("a", at: "2.0.0", with: [ - "a": ["c": (.versionSet(.range("1.0.0"..<"2.0.0")), .specific(["c"]))], - ]) + try builder.serve( + "a", + at: "2.0.0", + with: [ + "a": ["c": (.versionSet(.range("1.0.0"..<"2.0.0")), .specific(["c"]))] + ] + ) - try builder.serve("b", at: "1.0.0", with: [ - "b": ["c": (.versionSet(.range("2.0.0"..<"3.0.0")), .specific(["c"]))], - ]) - try builder.serve("b", at: "2.0.0", with: [ - "b": ["c": (.versionSet(.range("3.0.0"..<"4.0.0")), .specific(["c"]))], - ]) + try builder.serve( + "b", + at: "1.0.0", + with: [ + "b": ["c": (.versionSet(.range("2.0.0"..<"3.0.0")), .specific(["c"]))] + ] + ) + try builder.serve( + "b", + at: "2.0.0", + with: [ + "b": ["c": (.versionSet(.range("3.0.0"..<"4.0.0")), .specific(["c"]))] + ] + ) try builder.serve("c", at: "1.0.0") try builder.serve("c", at: "2.0.0") @@ -2700,34 +3327,53 @@ final class PubGrubBacktrackTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .version(v1)), - ("b", .version("2.0.0")), - ("c", .version("3.0.0")), - ]) + AssertResult( + result, + [ + ("a", .version(v1)), + ("b", .version("2.0.0")), + ("c", .version("3.0.0")), + ] + ) } func testBacktrack3() async throws { - try builder.serve("a", at: "1.0.0", with: [ - "a": ["x": (.versionSet(.range("1.0.0"..<"5.0.0")), .specific(["x"]))], - ]) - try builder.serve("b", at: "1.0.0", with: [ - "b": ["x": (.versionSet(.range("0.0.0"..<"2.0.0")), .specific(["x"]))], - ]) + try builder.serve( + "a", + at: "1.0.0", + with: [ + "a": ["x": (.versionSet(.range("1.0.0"..<"5.0.0")), .specific(["x"]))] + ] + ) + try builder.serve( + "b", + at: "1.0.0", + with: [ + "b": ["x": (.versionSet(.range("0.0.0"..<"2.0.0")), .specific(["x"]))] + ] + ) try builder.serve("c", at: "1.0.0") - try builder.serve("c", at: "2.0.0", with: [ - "c": [ - "a": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["a"])), - "b": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["b"])), + try builder.serve( + "c", + at: "2.0.0", + with: [ + "c": [ + "a": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["a"])), + "b": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["b"])), + ] ] - ]) + ) try builder.serve("x", at: "0.0.0") try builder.serve("x", at: "2.0.0") - try builder.serve("x", at: "1.0.0", with: [ - "x": ["y": (.versionSet(.exact(v1)), .specific(["y"]))], - ]) + try builder.serve( + "x", + at: "1.0.0", + with: [ + "x": ["y": (.versionSet(.exact(v1)), .specific(["y"]))] + ] + ) try builder.serve("y", at: "1.0.0") try builder.serve("y", at: "2.0.0") @@ -2740,33 +3386,52 @@ final class PubGrubBacktrackTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("c", .version(v1)), - ("y", .version("2.0.0")), - ]) + AssertResult( + result, + [ + ("c", .version(v1)), + ("y", .version("2.0.0")), + ] + ) } func testBacktrack4() async throws { - try builder.serve("a", at: "1.0.0", with: [ - "a": ["x": (.versionSet(.range("1.0.0"..<"5.0.0")), .specific(["x"]))], - ]) - try builder.serve("b", at: "1.0.0", with: [ - "b": ["x": (.versionSet(.range("0.0.0"..<"2.0.0")), .specific(["x"]))], - ]) + try builder.serve( + "a", + at: "1.0.0", + with: [ + "a": ["x": (.versionSet(.range("1.0.0"..<"5.0.0")), .specific(["x"]))] + ] + ) + try builder.serve( + "b", + at: "1.0.0", + with: [ + "b": ["x": (.versionSet(.range("0.0.0"..<"2.0.0")), .specific(["x"]))] + ] + ) try builder.serve("c", at: "1.0.0") - try builder.serve("c", at: "2.0.0", with: [ - "c": [ - "a": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["a"])), - "b": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["b"])), + try builder.serve( + "c", + at: "2.0.0", + with: [ + "c": [ + "a": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["a"])), + "b": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["b"])), + ] ] - ]) + ) try builder.serve("x", at: "0.0.0") try builder.serve("x", at: "2.0.0") - try builder.serve("x", at: "1.0.0", with: [ - "x": ["y": (.versionSet(.exact(v1)), .specific(["y"]))], - ]) + try builder.serve( + "x", + at: "1.0.0", + with: [ + "x": ["y": (.versionSet(.exact(v1)), .specific(["y"]))] + ] + ) try builder.serve("y", at: "1.0.0") try builder.serve("y", at: "2.0.0") @@ -2779,58 +3444,96 @@ final class PubGrubBacktrackTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("c", .version(v1)), - ("y", .version("2.0.0")), - ]) + AssertResult( + result, + [ + ("c", .version(v1)), + ("y", .version("2.0.0")), + ] + ) } func testBacktrack5() async throws { - try builder.serve("foo", at: "1.0.0", with: [ - "foo": ["bar": (.versionSet(.exact("1.0.0")), .specific(["bar"]))], - ]) - try builder.serve("foo", at: "2.0.0", with: [ - "foo": ["bar": (.versionSet(.exact("2.0.0")), .specific(["bar"]))], - ]) - try builder.serve("foo", at: "3.0.0", with: [ - "foo": ["bar": (.versionSet(.exact("3.0.0")), .specific(["bar"]))], - ]) + try builder.serve( + "foo", + at: "1.0.0", + with: [ + "foo": ["bar": (.versionSet(.exact("1.0.0")), .specific(["bar"]))] + ] + ) + try builder.serve( + "foo", + at: "2.0.0", + with: [ + "foo": ["bar": (.versionSet(.exact("2.0.0")), .specific(["bar"]))] + ] + ) + try builder.serve( + "foo", + at: "3.0.0", + with: [ + "foo": ["bar": (.versionSet(.exact("3.0.0")), .specific(["bar"]))] + ] + ) - try builder.serve("bar", at: "1.0.0", with: [ - "bar": ["baz": (.versionSet(.range("0.0.0"..<"3.0.0")), .specific(["baz"]))], - ]) - try builder.serve("bar", at: "2.0.0", with: [ - "bar": ["baz": (.versionSet(.exact("3.0.0")), .specific(["baz"]))], - ]) - try builder.serve("bar", at: "3.0.0", with: [ - "bar": ["baz": (.versionSet(.exact("3.0.0")), .specific(["baz"]))], - ]) + try builder.serve( + "bar", + at: "1.0.0", + with: [ + "bar": ["baz": (.versionSet(.range("0.0.0"..<"3.0.0")), .specific(["baz"]))] + ] + ) + try builder.serve( + "bar", + at: "2.0.0", + with: [ + "bar": ["baz": (.versionSet(.exact("3.0.0")), .specific(["baz"]))] + ] + ) + try builder.serve( + "bar", + at: "3.0.0", + with: [ + "bar": ["baz": (.versionSet(.exact("3.0.0")), .specific(["baz"]))] + ] + ) try builder.serve("baz", at: "1.0.0") let resolver = builder.create() let dependencies = try builder.create(dependencies: [ - "foo": (.versionSet(.range("1.0.0"..<"4.0.0")), .specific(["foo"])), + "foo": (.versionSet(.range("1.0.0"..<"4.0.0")), .specific(["foo"])) ]) let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("foo", .version(v1)), - ("bar", .version("1.0.0")), - ("baz", .version("1.0.0")), - ]) + AssertResult( + result, + [ + ("foo", .version(v1)), + ("bar", .version("1.0.0")), + ("baz", .version("1.0.0")), + ] + ) } func testBacktrack6() async throws { try builder.serve("a", at: "1.0.0") try builder.serve("a", at: "2.0.0") - try builder.serve("b", at: "1.0.0", with: [ - "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))], - ]) - try builder.serve("c", at: "1.0.0", with: [ - "c": ["b": (.versionSet(.range("0.0.0"..<"3.0.0")), .specific(["b"]))], - ]) + try builder.serve( + "b", + at: "1.0.0", + with: [ + "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))] + ] + ) + try builder.serve( + "c", + at: "1.0.0", + with: [ + "c": ["b": (.versionSet(.range("0.0.0"..<"3.0.0")), .specific(["b"]))] + ] + ) try builder.serve("d", at: "1.0.0") try builder.serve("d", at: "2.0.0") @@ -2843,23 +3546,34 @@ final class PubGrubBacktrackTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .version(v1)), - ("b", .version(v1)), - ("c", .version(v1)), - ("d", .version("2.0.0")), - ]) + AssertResult( + result, + [ + ("a", .version(v1)), + ("b", .version(v1)), + ("c", .version(v1)), + ("d", .version("2.0.0")), + ] + ) } func testLogging() async throws { try builder.serve("a", at: "1.0.0") try builder.serve("a", at: "2.0.0") - try builder.serve("b", at: "1.0.1", with: [ - "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))], - ]) - try builder.serve("c", at: "1.5.2", with: [ - "c": ["b": (.versionSet(.range("0.0.0"..<"3.0.0")), .specific(["b"]))], - ]) + try builder.serve( + "b", + at: "1.0.1", + with: [ + "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))] + ] + ) + try builder.serve( + "c", + at: "1.5.2", + with: [ + "c": ["b": (.versionSet(.range("0.0.0"..<"3.0.0")), .specific(["b"]))] + ] + ) try builder.serve("d", at: "1.0.1") try builder.serve("d", at: "2.3.0") @@ -2874,12 +3588,15 @@ final class PubGrubBacktrackTests: XCTestCase { let result = await resolver.solve(constraints: dependencies) - AssertResult(result, [ - ("a", .version("1.0.0")), - ("b", .version("1.0.1")), - ("c", .version("1.5.2")), - ("d", .version("2.3.0")), - ]) + AssertResult( + result, + [ + ("a", .version("1.0.0")), + ("b", .version("1.0.1")), + ("c", .version("1.5.2")), + ("d", .version("2.3.0")), + ] + ) observability.diagnostics.forEach { print("\($0)") } @@ -2890,19 +3607,27 @@ final class PubGrubBacktrackTests: XCTestCase { } func testPrereleaseVersionSelection() async throws { - try builder.serve("a", at: "1.0.0", with: [ - "a": [ - "b": (.versionSet(.range("0.0.8"..<"2.0.0")), .specific(["b"])) + try builder.serve( + "a", + at: "1.0.0", + with: [ + "a": [ + "b": (.versionSet(.range("0.0.8"..<"2.0.0")), .specific(["b"])) + ] ] - ]) + ) try builder.serve("b", at: "1.0.0-prerelease-20240710") - try builder.serve("c", at: "1.0.0", with: [ - "c": [ - "d": (.versionSet(.range("1.0.5"..<"2.0.0")), .specific(["d"])) + try builder.serve( + "c", + at: "1.0.0", + with: [ + "c": [ + "d": (.versionSet(.range("1.0.5"..<"2.0.0")), .specific(["d"])) + ] ] - ]) + ) try builder.serve("c", at: "1.0.1") try builder.serve("d", at: "1.0.0-prerelease-20240710") @@ -2913,31 +3638,41 @@ final class PubGrubBacktrackTests: XCTestCase { // The order matters here because solver used to assign `b` before `a`. let dependencies1 = try builder.create(dependencies: [ "a": (.versionSet(.exact("1.0.0")), .specific(["a"])), - "b": (.versionSet(.range("1.0.0-latest"..<"2.0.0")), .specific(["b"])) + "b": (.versionSet(.range("1.0.0-latest"..<"2.0.0")), .specific(["b"])), ]) - await AssertResult(resolver.solve(constraints: dependencies1), [ - ("a", .version("1.0.0")), - ("b", .version("1.0.0-prerelease-20240710")) - ]) + await AssertResult( + resolver.solve(constraints: dependencies1), + [ + ("a", .version("1.0.0")), + ("b", .version("1.0.0-prerelease-20240710")), + ] + ) let dependencies2 = try builder.create(dependencies: [ "c": (.versionSet(.exact("1.0.0")), .specific(["c"])), - "d": (.versionSet(.range("1.0.0-latest"..<"2.0.0")), .specific(["d"])) + "d": (.versionSet(.range("1.0.0-latest"..<"2.0.0")), .specific(["d"])), ]) - await AssertResult(resolver.solve(constraints: dependencies2), [ - ("c", .version("1.0.0")), - ("d", .version("1.0.6")) - ]) + await AssertResult( + resolver.solve(constraints: dependencies2), + [ + ("c", .version("1.0.0")), + ("d", .version("1.0.6")), + ] + ) } func testPrereleaseExactRequirement() async throws { - try builder.serve("c", at: "1.0.0", with: [ - "c": [ - "d": (.versionSet(.range("1.0.4"..<"2.0.0")), .specific(["d"])) + try builder.serve( + "c", + at: "1.0.0", + with: [ + "c": [ + "d": (.versionSet(.range("1.0.4"..<"2.0.0")), .specific(["d"])) + ] ] - ]) + ) try builder.serve("c", at: "1.0.1") try builder.serve("d", at: "1.0.0-prerelease-20240710") @@ -2948,7 +3683,7 @@ final class PubGrubBacktrackTests: XCTestCase { let exactDependencies = try builder.create(dependencies: [ "c": (.versionSet(.exact("1.0.0")), .specific(["c"])), - "d": (.versionSet(.exact("1.0.6-prerelease-1")), .specific(["d"])) + "d": (.versionSet(.exact("1.0.6-prerelease-1")), .specific(["d"])), ]) // FIXME: This should produce a valid solution but cannot at the @@ -2962,22 +3697,29 @@ final class PubGrubBacktrackTests: XCTestCase { let rangeDependency = try builder.create(dependencies: [ "c": (.versionSet(.exact("1.0.0")), .specific(["c"])), - "d": (.versionSet(.range("1.0.5"..<"1.0.6-prerelease-2")), .specific(["d"])) + "d": (.versionSet(.range("1.0.5"..<"1.0.6-prerelease-2")), .specific(["d"])), ]) let resultWithRange = await resolver.solve(constraints: rangeDependency) - AssertResult(resultWithRange, [ - ("c", .version("1.0.0")), - ("d", .version("1.0.6-prerelease-1")) - ]) + AssertResult( + resultWithRange, + [ + ("c", .version("1.0.0")), + ("d", .version("1.0.6-prerelease-1")), + ] + ) } func testReleaseOverPrerelease() async throws { - try builder.serve("a", at: "1.0.0", with: [ - "a": [ - "b": (.versionSet(.range("0.0.8"..<"2.0.0")), .specific(["b"])) + try builder.serve( + "a", + at: "1.0.0", + with: [ + "a": [ + "b": (.versionSet(.range("0.0.8"..<"2.0.0")), .specific(["b"])) + ] ] - ]) + ) try builder.serve("b", at: "1.0.0-prerelease-20240616") try builder.serve("b", at: "1.0.0") @@ -2986,31 +3728,41 @@ final class PubGrubBacktrackTests: XCTestCase { // The order matters here because solver used to assign `b` before `a`. let dependencies1 = try builder.create(dependencies: [ "a": (.versionSet(.exact("1.0.0")), .specific(["a"])), - "b": (.versionSet(.range("1.0.0-latest"..<"2.0.0")), .specific(["b"])) + "b": (.versionSet(.range("1.0.0-latest"..<"2.0.0")), .specific(["b"])), ]) - await AssertResult(resolver.solve(constraints: dependencies1), [ - ("a", .version("1.0.0")), - ("b", .version("1.0.0")) - ]) + await AssertResult( + resolver.solve(constraints: dependencies1), + [ + ("a", .version("1.0.0")), + ("b", .version("1.0.0")), + ] + ) let dependencies2 = try builder.create(dependencies: [ "b": (.versionSet(.range("1.0.0-latest"..<"2.0.0")), .specific(["b"])), - "a": (.versionSet(.exact("1.0.0")), .specific(["a"])) + "a": (.versionSet(.exact("1.0.0")), .specific(["a"])), ]) - await AssertResult(resolver.solve(constraints: dependencies2), [ - ("a", .version("1.0.0")), - ("b", .version("1.0.0")) - ]) + await AssertResult( + resolver.solve(constraints: dependencies2), + [ + ("a", .version("1.0.0")), + ("b", .version("1.0.0")), + ] + ) } func testPrereleaseInferenceThroughDependencies() async throws { - try builder.serve("a", at: "1.0.0", with: [ - "a": [ - "b": (.versionSet(.range("1.0.0"..<"2.0.0-latest")), .specific(["b"])) + try builder.serve( + "a", + at: "1.0.0", + with: [ + "a": [ + "b": (.versionSet(.range("1.0.0"..<"2.0.0-latest")), .specific(["b"])) + ] ] - ]) + ) try builder.serve("b", at: "0.0.8-prerelease-20230310") try builder.serve("b", at: "0.0.8") @@ -3022,23 +3774,29 @@ final class PubGrubBacktrackTests: XCTestCase { // The order matters here because solver used to assign `b` before `a`. let dependencies1 = try builder.create(dependencies: [ "a": (.versionSet(.exact("1.0.0")), .specific(["a"])), - "b": (.versionSet(.range("0.0.8"..<"2.0.0")), .specific(["b"])) + "b": (.versionSet(.range("0.0.8"..<"2.0.0")), .specific(["b"])), ]) - await AssertResult(resolver.solve(constraints: dependencies1), [ - ("a", .version("1.0.0")), - ("b", .version("1.9.9-prerelease-20240702")) - ]) + await AssertResult( + resolver.solve(constraints: dependencies1), + [ + ("a", .version("1.0.0")), + ("b", .version("1.9.9-prerelease-20240702")), + ] + ) let dependencies2 = try builder.create(dependencies: [ "b": (.versionSet(.range("0.0.8"..<"2.0.0")), .specific(["b"])), - "a": (.versionSet(.exact("1.0.0")), .specific(["a"])) + "a": (.versionSet(.exact("1.0.0")), .specific(["a"])), ]) - await AssertResult(resolver.solve(constraints: dependencies2), [ - ("a", .version("1.0.0")), - ("b", .version("1.9.9-prerelease-20240702")) - ]) + await AssertResult( + resolver.solve(constraints: dependencies2), + [ + ("a", .version("1.0.0")), + ("b", .version("1.9.9-prerelease-20240702")), + ] + ) } } @@ -3058,7 +3816,8 @@ private func AssertBindings( line: UInt = #line ) { if bindings.count > packages.count { - let unexpectedBindings = bindings + let unexpectedBindings = + bindings .filter { binding in packages.contains(where: { pkg in pkg.identity != binding.package.identity @@ -3138,7 +3897,7 @@ public class MockContainer: PackageContainer { return versions } - public func versionsAscending() throws -> [Version] { + public func versionsAscending() throws -> [Version] { var versions: [Version] = [] for version in self._versions { guard case .version(let v) = version else { continue } @@ -3214,7 +3973,8 @@ public class MockContainer: PackageContainer { unversionedDependencies: [(package: PackageReference, requirement: PackageRequirement, productFilter: ProductFilter)] ) { self.init(package: package) - self.unversionedDeps = unversionedDependencies + self.unversionedDeps = + unversionedDependencies .map { PackageContainerConstraint(package: $0.package, requirement: $0.requirement, products: $0.productFilter) } } @@ -3224,7 +3984,8 @@ public class MockContainer: PackageContainer { package: PackageReference, requirement: VersionSetSpecifier, productFilter: ProductFilter - )]]]) { + )]]] + ) { var dependencies: [String: [String: [Dependency]]] = [:] for (version, productDependencies) in dependenciesByVersion { if dependencies[version.description] == nil { @@ -3246,7 +4007,8 @@ public class MockContainer: PackageContainer { self.package = package self.dependencies = dependencies let versions = dependencies.keys.compactMap(Version.init(_:)) - self._versions = versions + self._versions = + versions .sorted() .map(BoundVersion.version) } @@ -3316,7 +4078,7 @@ class DependencyGraphBuilder { toolsVersion: ToolsVersion? = nil, with dependencies: KeyValuePairs> = [:] ) throws { - try self.serve(package, at: versions.map{ .version($0) }, toolsVersion: toolsVersion, with: dependencies) + try self.serve(package, at: versions.map { .version($0) }, toolsVersion: toolsVersion, with: dependencies) } func serve( @@ -3415,7 +4177,6 @@ class DependencyGraphBuilder { return store } - func create( resolvedPackages: ResolvedPackagesStore.ResolvedPackages = [:], delegate: DependencyResolverDelegate? = .none @@ -3472,13 +4233,14 @@ extension Term { guard case let .versionSet(vs) = requirement! else { fatalError() } - self.init(node: .product(packageReference.identity.description, package: packageReference), - requirement: vs, - isPositive: isPositive) + self.init( + node: .product(packageReference.identity.description, package: packageReference), + requirement: vs, + isPositive: isPositive + ) } } - extension PackageReference { public init(stringLiteral value: String) { let ref = PackageReference.localSourceControl(identity: .plain(value), path: .root) @@ -3504,7 +4266,7 @@ extension Result where Success == [DependencyResolverBinding] { return error.description default: XCTFail("Unexpected result \(self)") - } + } default: XCTFail("Unexpected result \(self)") } diff --git a/Tests/PackageGraphTests/ResolvedTargetTests.swift b/Tests/PackageGraphTests/ResolvedTargetTests.swift index b33aeb9cb43..4e38b54f147 100644 --- a/Tests/PackageGraphTests/ResolvedTargetTests.swift +++ b/Tests/PackageGraphTests/ResolvedTargetTests.swift @@ -101,7 +101,7 @@ final class ResolvedModuleDependencyTests: XCTestCase { name: "t6", deps: t4, t5 - ) // same as above, but these two swapped + ) // same as above, but these two swapped // precise order is not important, but it is important that the following are true let t6rd = try t6.recursiveModuleDependencies().map(\.id) diff --git a/Tests/PackageGraphTests/TopologicalSortTests.swift b/Tests/PackageGraphTests/TopologicalSortTests.swift index 650c340167b..d2006a97b12 100644 --- a/Tests/PackageGraphTests/TopologicalSortTests.swift +++ b/Tests/PackageGraphTests/TopologicalSortTests.swift @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// - @testable import PackageGraph import XCTest @@ -53,7 +52,7 @@ final class TopologicalSortTests: XCTestCase { let diamond: [Int: [Int]] = [ 1: [3, 2], 2: [4], - 3: [4] + 3: [4], ] XCTAssertEqual([1, 2, 3, 4], try topologicalSort(1, diamond)) XCTAssertEqual([2, 3, 4], try topologicalSort([3, 2], diamond)) diff --git a/Tests/PackageGraphTests/VersionSetSpecifierTests.swift b/Tests/PackageGraphTests/VersionSetSpecifierTests.swift index 6fa280c8815..646c00f384a 100644 --- a/Tests/PackageGraphTests/VersionSetSpecifierTests.swift +++ b/Tests/PackageGraphTests/VersionSetSpecifierTests.swift @@ -101,7 +101,6 @@ final class VersionSetSpecifierTests: XCTestCase { XCTAssertEqual(VersionSetSpecifier.ranges(["3.2.0"..<"3.2.3", "3.2.4"..<"4.0.0"]).difference(.exact("3.2.2")), .ranges(["3.2.0"..<"3.2.2", "3.2.4"..<"4.0.0"])) XCTAssertEqual(VersionSetSpecifier.ranges(["3.2.0"..<"3.2.1", "3.2.3"..<"4.0.0"]).difference(.exact("3.2.0")), .range("3.2.3"..<"4.0.0")) - XCTAssertEqual(VersionSetSpecifier.exact("1.0.0-beta").difference(.exact("1.0.0-beta")), .empty) XCTAssertEqual(VersionSetSpecifier.exact("2.0.0-beta").difference(.exact("1.0.0")), .exact("2.0.0-beta")) XCTAssertEqual(VersionSetSpecifier.exact("2.0.0-beta").difference(.exact("1.0.0-beta")), .exact("2.0.0-beta")) @@ -114,12 +113,12 @@ final class VersionSetSpecifierTests: XCTestCase { XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta"..<"2.0.0").difference(.exact("1.0.0-beta")), .range("1.0.0-beta.0"..<"2.0.0")) XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta"..<"2.0.0").difference(.exact("1.0.0-beta.5")), .ranges(["1.0.0-beta"..<"1.0.0-beta.5", "1.0.0-beta.5.0"..<"2.0.0"])) - XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta"..<"2.0.0").difference(.range("1.0.0-beta.3" ..< "2.0.0")), .range("1.0.0-beta"..<"1.0.0-beta.3")) - XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta.5"..<"1.0.0-beta.30").difference(.range("1.0.0-beta.10" ..< "2.0.0")), .range("1.0.0-beta.5"..<"1.0.0-beta.10")) - XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta"..<"1.0.0-beta.30").difference(.range("1.0.0-beta.3" ..< "1.0.0-beta.10")), .ranges(["1.0.0-beta"..<"1.0.0-beta.3", "1.0.0-beta.10"..<"1.0.0-beta.30"])) + XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta"..<"2.0.0").difference(.range("1.0.0-beta.3"..<"2.0.0")), .range("1.0.0-beta"..<"1.0.0-beta.3")) + XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta.5"..<"1.0.0-beta.30").difference(.range("1.0.0-beta.10"..<"2.0.0")), .range("1.0.0-beta.5"..<"1.0.0-beta.10")) + XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta"..<"1.0.0-beta.30").difference(.range("1.0.0-beta.3"..<"1.0.0-beta.10")), .ranges(["1.0.0-beta"..<"1.0.0-beta.3", "1.0.0-beta.10"..<"1.0.0-beta.30"])) - XCTAssertEqual(VersionSetSpecifier.range("1.0.0-alpha"..<"2.0.0").difference(.range("1.0.0-beta" ..< "2.0.0")), .range("1.0.0-alpha"..<"1.0.0-beta")) - XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta"..<"2.0.0").difference(.range("1.0.0-alpha" ..< "2.0.0")), .empty) + XCTAssertEqual(VersionSetSpecifier.range("1.0.0-alpha"..<"2.0.0").difference(.range("1.0.0-beta"..<"2.0.0")), .range("1.0.0-alpha"..<"1.0.0-beta")) + XCTAssertEqual(VersionSetSpecifier.range("1.0.0-beta"..<"2.0.0").difference(.range("1.0.0-alpha"..<"2.0.0")), .empty) } func testEquality() { @@ -159,22 +158,28 @@ final class VersionSetSpecifierTests: XCTestCase { XCTAssertFalse(VersionSetSpecifier.exact("0.0.1").supportsPrereleases) XCTAssertTrue(VersionSetSpecifier.exact("0.0.1-latest").supportsPrereleases) - XCTAssertTrue(VersionSetSpecifier.range("0.0.1-latest" ..< "2.0.0").supportsPrereleases) - XCTAssertTrue(VersionSetSpecifier.range("0.0.1" ..< "2.0.0-latest").supportsPrereleases) - - XCTAssertTrue(VersionSetSpecifier.ranges([ - "0.0.1" ..< "0.0.2", - "0.0.1" ..< "2.0.0-latest", - ]).supportsPrereleases) - - XCTAssertTrue(VersionSetSpecifier.ranges([ - "0.0.1-latest" ..< "0.0.2", - "0.0.1" ..< "2.0.0", - ]).supportsPrereleases) - - XCTAssertFalse(VersionSetSpecifier.ranges([ - "0.0.1" ..< "0.0.2", - "0.0.1" ..< "2.0.0", - ]).supportsPrereleases) + XCTAssertTrue(VersionSetSpecifier.range("0.0.1-latest"..<"2.0.0").supportsPrereleases) + XCTAssertTrue(VersionSetSpecifier.range("0.0.1"..<"2.0.0-latest").supportsPrereleases) + + XCTAssertTrue( + VersionSetSpecifier.ranges([ + "0.0.1"..<"0.0.2", + "0.0.1"..<"2.0.0-latest", + ]).supportsPrereleases + ) + + XCTAssertTrue( + VersionSetSpecifier.ranges([ + "0.0.1-latest"..<"0.0.2", + "0.0.1"..<"2.0.0", + ]).supportsPrereleases + ) + + XCTAssertFalse( + VersionSetSpecifier.ranges([ + "0.0.1"..<"0.0.2", + "0.0.1"..<"2.0.0", + ]).supportsPrereleases + ) } } diff --git a/Tests/PackageLoadingTests/Inputs/package-deps-manifest.swift b/Tests/PackageLoadingTests/Inputs/package-deps-manifest.swift index d671cb28fe0..a7da1c8fffb 100644 --- a/Tests/PackageLoadingTests/Inputs/package-deps-manifest.swift +++ b/Tests/PackageLoadingTests/Inputs/package-deps-manifest.swift @@ -3,4 +3,6 @@ import PackageDescription let package = Package( name: "PackageDeps", dependencies: [ - .Package(url: "https://example.com/example", majorVersion: 1)]) + .Package(url: "https://example.com/example", majorVersion: 1) + ] +) diff --git a/Tests/PackageLoadingTests/Inputs/target-deps-manifest.swift b/Tests/PackageLoadingTests/Inputs/target-deps-manifest.swift index d7a1bcbb198..4ba5daf634d 100644 --- a/Tests/PackageLoadingTests/Inputs/target-deps-manifest.swift +++ b/Tests/PackageLoadingTests/Inputs/target-deps-manifest.swift @@ -5,7 +5,11 @@ let package = Package( targets: [ Target( name: "sys", - dependencies: [.Target(name: "libc")]), + dependencies: [.Target(name: "libc")] + ), Target( name: "dep", - dependencies: [.Target(name: "sys"), .Target(name: "libc")])]) + dependencies: [.Target(name: "sys"), .Target(name: "libc")] + ), + ] +) diff --git a/Tests/PackageLoadingTests/ManifestLoaderCacheTests.swift b/Tests/PackageLoadingTests/ManifestLoaderCacheTests.swift index b6f46beab36..52617be534b 100644 --- a/Tests/PackageLoadingTests/ManifestLoaderCacheTests.swift +++ b/Tests/PackageLoadingTests/ManifestLoaderCacheTests.swift @@ -53,13 +53,15 @@ final class ManifestLoaderCacheTests: XCTestCase { func check(loader: ManifestLoader, expectCached: Bool) async throws { delegate.clear() - let manifest = try await XCTAsyncUnwrap(try await loader.load( - manifestPath: manifestPath, - packageKind: .root(manifestPath.parentDirectory), - toolsVersion: .current, - fileSystem: fileSystem, - observabilityScope: observability.topScope - )) + let manifest = try await XCTAsyncUnwrap( + try await loader.load( + manifestPath: manifestPath, + packageKind: .root(manifestPath.parentDirectory), + toolsVersion: .current, + fileSystem: fileSystem, + observabilityScope: observability.topScope + ) + ) XCTAssertNoDiagnostics(observability.diagnostics) try await XCTAssertAsyncEqual(try await delegate.loaded(timeout: .seconds(1)), [manifestPath]) @@ -146,13 +148,15 @@ final class ManifestLoaderCacheTests: XCTestCase { func check(loader: ManifestLoader, expectCached: Bool) async throws { delegate.clear() - let manifest = try await XCTAsyncUnwrap(try await loader.load( - manifestPath: manifestPath, - packageKind: .root(manifestPath.parentDirectory), - toolsVersion: .current, - fileSystem: fileSystem, - observabilityScope: observability.topScope - )) + let manifest = try await XCTAsyncUnwrap( + try await loader.load( + manifestPath: manifestPath, + packageKind: .root(manifestPath.parentDirectory), + toolsVersion: .current, + fileSystem: fileSystem, + observabilityScope: observability.topScope + ) + ) XCTAssertNoDiagnostics(observability.diagnostics) try await XCTAssertAsyncEqual(try await delegate.loaded(timeout: .seconds(1)), [manifestPath]) @@ -205,14 +209,14 @@ final class ManifestLoaderCacheTests: XCTestCase { func testContentBasedCaching() async throws { try await testWithTemporaryDirectory { path in let manifest = """ - import PackageDescription - let package = Package( - name: "Trivial", - targets: [ - .target(name: "foo"), - ] - ) - """ + import PackageDescription + let package = Package( + name: "Trivial", + targets: [ + .target(name: "foo"), + ] + ) + """ let delegate = ManifestTestDelegate() @@ -304,13 +308,15 @@ final class ManifestLoaderCacheTests: XCTestCase { delegate: delegate ) - let manifest = try await XCTAsyncUnwrap(try await loader.load( - manifestPath: manifestPath, - packageKind: .root(manifestPath.parentDirectory), - toolsVersion: .current, - fileSystem: fileSystem, - observabilityScope: observability.topScope - )) + let manifest = try await XCTAsyncUnwrap( + try await loader.load( + manifestPath: manifestPath, + packageKind: .root(manifestPath.parentDirectory), + toolsVersion: .current, + fileSystem: fileSystem, + observabilityScope: observability.topScope + ) + ) XCTAssertNoDiagnostics(observability.diagnostics) try await XCTAssertAsyncEqual(try await delegate.loaded(timeout: .seconds(1)), [manifestPath]) @@ -369,13 +375,15 @@ final class ManifestLoaderCacheTests: XCTestCase { func check(loader: ManifestLoader, expectCached: Bool) async throws { delegate.clear() - let manifest = try await XCTAsyncUnwrap(try await loader.load( - manifestPath: manifestPath, - packageKind: .root(manifestPath.parentDirectory), - toolsVersion: .current, - fileSystem: fileSystem, - observabilityScope: observability.topScope - )) + let manifest = try await XCTAsyncUnwrap( + try await loader.load( + manifestPath: manifestPath, + packageKind: .root(manifestPath.parentDirectory), + toolsVersion: .current, + fileSystem: fileSystem, + observabilityScope: observability.topScope + ) + ) XCTAssertNoDiagnostics(observability.diagnostics) try await XCTAssertAsyncEqual(try await delegate.loaded(timeout: .seconds(1)), [manifestPath]) @@ -419,13 +427,15 @@ final class ManifestLoaderCacheTests: XCTestCase { func check(loader: ManifestLoader, expectCached: Bool) async throws { delegate.clear() - let manifest = try await XCTAsyncUnwrap(try await loader.load( - manifestPath: manifestPath, - packageKind: .root(manifestPath.parentDirectory), - toolsVersion: .current, - fileSystem: fileSystem, - observabilityScope: observability.topScope - )) + let manifest = try await XCTAsyncUnwrap( + try await loader.load( + manifestPath: manifestPath, + packageKind: .root(manifestPath.parentDirectory), + toolsVersion: .current, + fileSystem: fileSystem, + observabilityScope: observability.topScope + ) + ) XCTAssertNoDiagnostics(observability.diagnostics) try await XCTAssertAsyncEqual(try await delegate.loaded(timeout: .seconds(1)), [manifestPath]) @@ -510,7 +520,7 @@ final class ManifestLoaderCacheTests: XCTestCase { } XCTAssertNoDiagnostics(validationDiagnostics) - let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map{ ($0.identity.description, $0) }) + let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map { ($0.identity.description, $0) }) XCTAssertEqual(deps["foo"], .remoteSourceControl(url: "https://scm.com/foo", requirement: .upToNextMajor(from: "1.0.0"))) XCTAssertEqual(deps["bar"], .remoteSourceControl(url: "https://scm.com/bar", requirement: .upToNextMajor(from: "2.1.0"))) } @@ -534,7 +544,7 @@ final class ManifestLoaderCacheTests: XCTestCase { } XCTAssertNoDiagnostics(validationDiagnostics) - let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map{ ($0.identity.description, $0) }) + let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map { ($0.identity.description, $0) }) XCTAssertEqual(deps["foo"], .remoteSourceControl(url: "https://scm.com/foo", requirement: .upToNextMajor(from: "1.0.0"))) XCTAssertEqual(deps["bar"], .remoteSourceControl(url: "https://scm.com/bar", requirement: .upToNextMajor(from: "2.1.0"))) } @@ -559,7 +569,7 @@ final class ManifestLoaderCacheTests: XCTestCase { } XCTAssertNoDiagnostics(validationDiagnostics) - let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map{ ($0.identity.description, $0) }) + let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map { ($0.identity.description, $0) }) XCTAssertEqual(deps["foo"], .remoteSourceControl(url: "https://scm.com/foo", requirement: .upToNextMajor(from: "1.0.0"))) XCTAssertEqual(deps["bar"], .remoteSourceControl(url: "https://scm.com/bar", requirement: .upToNextMajor(from: "2.1.0"))) } @@ -583,7 +593,7 @@ final class ManifestLoaderCacheTests: XCTestCase { } XCTAssertNoDiagnostics(validationDiagnostics) - let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map{ ($0.identity.description, $0) }) + let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map { ($0.identity.description, $0) }) XCTAssertEqual(deps["foo"], .remoteSourceControl(url: "https://scm.com/foo", requirement: .upToNextMajor(from: "1.0.0"))) XCTAssertEqual(deps["bar"], .remoteSourceControl(url: "https://scm.com/bar", requirement: .upToNextMajor(from: "2.1.0"))) } @@ -593,10 +603,10 @@ final class ManifestLoaderCacheTests: XCTestCase { private func makeMockManifests( fileSystem: FileSystem, rootPath: AbsolutePath, - count: Int = Int.random(in: 50 ..< 100) + count: Int = Int.random(in: 50..<100) ) throws -> [ManifestLoader.CacheKey: ManifestLoader.EvaluationResult] { var manifests = [ManifestLoader.CacheKey: ManifestLoader.EvaluationResult]() - for index in 0 ..< count { + for index in 0.. () ) async throws { let observability = ObservabilitySystem.makeForTesting() diff --git a/Tests/PackageLoadingTests/PD_6_2_LoadingTests.swift b/Tests/PackageLoadingTests/PD_6_2_LoadingTests.swift index cd394f6a5f1..778eee12c93 100644 --- a/Tests/PackageLoadingTests/PD_6_2_LoadingTests.swift +++ b/Tests/PackageLoadingTests/PD_6_2_LoadingTests.swift @@ -73,7 +73,8 @@ struct PackageDescription6_2LoadingTests { let observability = ObservabilitySystem.makeForTesting() try await withKnownIssue("https://github.com/swiftlang/swift-package-manager/issues/8543: there are compilation errors on Windows") { - let (_, validationDiagnostics) = try await PackageDescriptionLoadingTests + let (_, validationDiagnostics) = + try await PackageDescriptionLoadingTests .loadAndValidateManifest( content, toolsVersion: .v6_2, @@ -96,9 +97,9 @@ struct PackageDescription6_2LoadingTests { } private var isWindows: Bool { -#if os(Windows) - true -#else - false -#endif + #if os(Windows) + true + #else + false + #endif } diff --git a/Tests/PackageLoadingTests/PackageBuilderTests.swift b/Tests/PackageLoadingTests/PackageBuilderTests.swift index 0dd27697125..dea82a48557 100644 --- a/Tests/PackageLoadingTests/PackageBuilderTests.swift +++ b/Tests/PackageLoadingTests/PackageBuilderTests.swift @@ -25,15 +25,17 @@ import Testing struct PackageBuilderTests { @Test func testDotFilesAreIgnored() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/foo/.Bar.swift", - "/Sources/foo/Foo.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/foo/.Bar.swift", + "/Sources/foo/Foo.swift" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", path: .root, targets: [ - try TargetDescription(name: "foo"), + try TargetDescription(name: "foo") ] ) try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -46,15 +48,17 @@ struct PackageBuilderTests { @Test func testXCPrivacyIgnored() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/foo/PrivacyInfo.xcprivacy", - "/Sources/foo/Foo.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/foo/PrivacyInfo.xcprivacy", + "/Sources/foo/Foo.swift" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", path: .root, targets: [ - try TargetDescription(name: "foo"), + try TargetDescription(name: "foo") ] ) try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -70,8 +74,9 @@ struct PackageBuilderTests { func testMixedSources() throws { let foo: AbsolutePath = "/Sources/foo" - let fs = InMemoryFileSystem(emptyFiles: - foo.appending(components: "main.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + foo.appending(components: "main.swift").pathString, foo.appending(components: "main.c").pathString ) @@ -79,7 +84,7 @@ struct PackageBuilderTests { displayName: "pkg", path: .root, targets: [ - try TargetDescription(name: "foo"), + try TargetDescription(name: "foo") ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -107,7 +112,7 @@ struct PackageBuilderTests { displayName: "pkg", path: path, targets: [ - try TargetDescription(name: "foo"), + try TargetDescription(name: "foo") ] ) @@ -138,7 +143,7 @@ struct PackageBuilderTests { let manifest = Manifest.createRootManifest( displayName: "pkg", targets: [ - try TargetDescription(name: "bar"), + try TargetDescription(name: "bar") ] ) @@ -150,9 +155,11 @@ struct PackageBuilderTests { @Test func testCInTests() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/MyPackage/main.swift", - "/Tests/MyPackageTests/abc.c") + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/MyPackage/main.swift", + "/Tests/MyPackageTests/abc.c" + ) let manifest = Manifest.createRootManifest( displayName: "MyPackage", @@ -175,32 +182,34 @@ struct PackageBuilderTests { package.checkProduct("MyPackage") { _ in } #if os(Linux) - diagnostics.check( - diagnostic: "ignoring target 'MyPackageTests' in package '\(package.packageIdentity)'; C language in tests is not yet supported", - severity: .warning - ) + diagnostics.check( + diagnostic: "ignoring target 'MyPackageTests' in package '\(package.packageIdentity)'; C language in tests is not yet supported", + severity: .warning + ) #elseif os(macOS) || os(Android) || os(Windows) - package.checkProduct("MyPackagePackageTests") { _ in } + package.checkProduct("MyPackagePackageTests") { _ in } #endif } } @Test func testValidSources() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/pkg/main.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/pkg/main.swift", "/Sources/pkg/noExtension", "/Sources/pkg/Package.swift", "/.git/anchor", "/.xcodeproj/anchor", "/.playground/anchor", "/Package.swift", - "/Packages/MyPackage/main.c") + "/Packages/MyPackage/main.c" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", targets: [ - try TargetDescription(name: "pkg"), + try TargetDescription(name: "pkg") ] ) try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -214,17 +223,19 @@ struct PackageBuilderTests { @Test func testVersionSpecificManifests() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Package.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Package.swift", "/Package@swift-999.swift", "/Sources/Foo/Package.swift", - "/Sources/Foo/Package@swift-1.swift") + "/Sources/Foo/Package@swift-1.swift" + ) let name = "Foo" let manifest = Manifest.createRootManifest( displayName: name, targets: [ - try TargetDescription(name: name), + try TargetDescription(name: name) ] ) try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -237,8 +248,9 @@ struct PackageBuilderTests { @Test func testModuleMapLayout() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/clib/include/module.modulemap", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/clib/include/module.modulemap", "/Sources/clib/include/clib.h", "/Sources/clib/clib.c" ) @@ -246,7 +258,7 @@ struct PackageBuilderTests { let manifest = Manifest.createRootManifest( displayName: "MyPackage", targets: [ - try TargetDescription(name: "clib"), + try TargetDescription(name: "clib") ] ) try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -262,8 +274,9 @@ struct PackageBuilderTests { func testPublicIncludeDirMixedWithSources() throws { let Sources: AbsolutePath = "/Sources" - let fs = InMemoryFileSystem(emptyFiles: - Sources.appending(components: "clib", "nested", "nested.h").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + Sources.appending(components: "clib", "nested", "nested.h").pathString, Sources.appending(components: "clib", "nested", "nested.c").pathString, Sources.appending(components: "clib", "clib.h").pathString, Sources.appending(components: "clib", "clib.c").pathString, @@ -280,7 +293,7 @@ struct PackageBuilderTests { path: "Sources", sources: ["clib", "clib"], publicHeadersPath: "." - ), + ) ] ) try PackageBuilderTester(manifest, in: fs) { package, diags in @@ -300,8 +313,9 @@ struct PackageBuilderTests { func testDeclaredSourcesWithDot() throws { let swiftLib: RelativePath = RelativePath("swift.lib") - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/swift.lib/foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/swift.lib/foo.swift", "/Sources/swiftlib1/swift.lib/foo.swift", "/Sources/swiftlib2/swift.lib/foo.swift", "/Sources/swiftlib3/swift.lib/foo.swift", @@ -348,8 +362,9 @@ struct PackageBuilderTests { @Test func testOverlappingDeclaredSources() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/clib/subfolder/foo.h", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/clib/subfolder/foo.h", "/Sources/clib/subfolder/foo.c", "/Sources/clib/bar.h", "/Sources/clib/bar.c", @@ -363,7 +378,7 @@ struct PackageBuilderTests { name: "clib", path: "Sources", sources: ["clib", "clib/subfolder"] - ), + ) ] ) try PackageBuilderTester(manifest, in: fs) { result, _ in @@ -377,15 +392,16 @@ struct PackageBuilderTests { func testDeclaredExecutableProducts() throws { // Check that declaring executable product doesn't collide with the // inferred products. - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/exec/main.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/exec/main.swift", "/Sources/foo/foo.swift" ) var manifest = Manifest.createRootManifest( displayName: "pkg", products: [ - try ProductDescription(name: "exec", type: .executable, targets: ["exec", "foo"]), + try ProductDescription(name: "exec", type: .executable, targets: ["exec", "foo"]) ], targets: [ try TargetDescription(name: "foo"), @@ -421,7 +437,7 @@ struct PackageBuilderTests { manifest = Manifest.createRootManifest( displayName: "pkg", products: [ - try ProductDescription(name: "exec1", type: .executable, targets: ["exec"]), + try ProductDescription(name: "exec1", type: .executable, targets: ["exec"]) ], targets: [ try TargetDescription(name: "foo"), @@ -439,8 +455,9 @@ struct PackageBuilderTests { @Test func testExecutableTargets() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/exec1/exec.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/exec1/exec.swift", "/Sources/exec2/main.swift", "/Sources/lib/lib.swift" ) @@ -450,7 +467,7 @@ struct PackageBuilderTests { displayName: "pkg", toolsVersion: .v5_5, products: [ - try ProductDescription(name: "exec1", type: .executable, targets: ["exec1", "lib"]), + try ProductDescription(name: "exec1", type: .executable, targets: ["exec1", "lib"]) ], targets: [ try TargetDescription(name: "exec1", type: .executable), @@ -488,7 +505,7 @@ struct PackageBuilderTests { displayName: "pkg", toolsVersion: .v5_5, products: [ - try ProductDescription(name: "exec1", type: .executable, targets: ["exec1"]), + try ProductDescription(name: "exec1", type: .executable, targets: ["exec1"]) ], targets: [ try TargetDescription(name: "lib"), @@ -508,7 +525,7 @@ struct PackageBuilderTests { displayName: "pkg", toolsVersion: .v5_5, products: [ - try ProductDescription(name: "exec1", type: .executable, targets: ["exec1"]), + try ProductDescription(name: "exec1", type: .executable, targets: ["exec1"]) ], targets: [ try TargetDescription(name: "lib"), @@ -528,7 +545,7 @@ struct PackageBuilderTests { displayName: "pkg", toolsVersion: .v5_5, products: [ - try ProductDescription(name: "exec2", type: .executable, targets: ["exec2"]), + try ProductDescription(name: "exec2", type: .executable, targets: ["exec2"]) ], targets: [ try TargetDescription(name: "lib"), @@ -551,8 +568,9 @@ struct PackageBuilderTests { @Test func testTestEntryPointFound() throws { try SwiftModule.testEntryPointNames.forEach { name in - let fs = InMemoryFileSystem(emptyFiles: - "/swift/exe/foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/swift/exe/foo.swift", "/\(name)", "/swift/tests/footests.swift" ) @@ -594,36 +612,37 @@ struct PackageBuilderTests { ) func testTestManifestSearch() throws { try withKnownIssue(isIntermittent: true) { - let fs = InMemoryFileSystem(emptyFiles: - "/pkg/foo.swift", - "/pkg/footests.swift" - ) + let fs = InMemoryFileSystem( + emptyFiles: + "/pkg/foo.swift", + "/pkg/footests.swift" + ) - let manifest = Manifest.createRootManifest( - displayName: "pkg", - targets: [ - try TargetDescription( - name: "exe", - path: "./", - sources: ["foo.swift"] - ), - try TargetDescription( - name: "tests", - path: "./", - sources: ["footests.swift"], - type: .test - ), - ] - ) - try PackageBuilderTester(manifest, path: "/pkg", in: fs) { package, _ in - try package.checkModule("exe") { _ in } - try package.checkModule("tests") { _ in } + let manifest = Manifest.createRootManifest( + displayName: "pkg", + targets: [ + try TargetDescription( + name: "exe", + path: "./", + sources: ["foo.swift"] + ), + try TargetDescription( + name: "tests", + path: "./", + sources: ["footests.swift"], + type: .test + ), + ] + ) + try PackageBuilderTester(manifest, path: "/pkg", in: fs) { package, _ in + try package.checkModule("exe") { _ in } + try package.checkModule("tests") { _ in } - package.checkProduct("pkgPackageTests") { product in - product.check(type: .test, targets: ["tests"]) - product.check(testEntryPointPath: nil) + package.checkProduct("pkgPackageTests") { product in + product.check(type: .test, targets: ["tests"]) + product.check(testEntryPointPath: nil) + } } - } } when: { ProcessInfo.hostOperatingSystem == .windows } @@ -636,10 +655,10 @@ struct PackageBuilderTests { let manifest = Manifest.createRootManifest( displayName: "pkg", products: [ - try ProductDescription(name: "", type: .library(.automatic), targets: ["best"]), + try ProductDescription(name: "", type: .library(.automatic), targets: ["best"]) ], targets: [ - try TargetDescription(name: "best"), + try TargetDescription(name: "best") ] ) @@ -653,8 +672,9 @@ struct PackageBuilderTests { let name = SwiftModule.defaultTestEntryPointName let swift: AbsolutePath = "/swift" - let fs = InMemoryFileSystem(emptyFiles: - AbsolutePath.root.appending(components: name).pathString, + let fs = InMemoryFileSystem( + emptyFiles: + AbsolutePath.root.appending(components: name).pathString, swift.appending(components: name).pathString, swift.appending(components: "tests", "footests.swift").pathString ) @@ -666,7 +686,7 @@ struct PackageBuilderTests { name: "tests", path: "swift/tests", type: .test - ), + ) ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -680,8 +700,9 @@ struct PackageBuilderTests { let swift: RelativePath = "swift" let bar: AbsolutePath = "/bar" - let fs = InMemoryFileSystem(emptyFiles: - "/mah/target/exe/swift/exe/main.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/mah/target/exe/swift/exe/main.swift", "/mah/target/exe/swift/exe/foo.swift", "/mah/target/exe/swift/bar.swift", "/mah/target/exe/shouldBeIgnored.swift", @@ -699,18 +720,22 @@ struct PackageBuilderTests { try TargetDescription( name: "exe", path: "mah/target/exe", - sources: [swift.pathString]), + sources: [swift.pathString] + ), try TargetDescription( name: "clib", path: "mah/target/exe", - sources: ["foo.c"]), + sources: ["foo.c"] + ), try TargetDescription( - name: "foo"), + name: "foo" + ), try TargetDescription( name: "bar", path: "bar", exclude: ["bar/excluded.swift", "bar/fixture"], - sources: ["bar"]), + sources: ["bar"] + ), ] ) try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -718,8 +743,12 @@ struct PackageBuilderTests { try package.checkModule("exe") { module in module.check(c99name: "exe", type: .executable) - module.checkSources(root: "/mah/target/exe", - paths: swift.appending(components: "exe", "main.swift").pathString, swift.appending(components: "exe", "foo.swift").pathString, swift.appending(components: "bar.swift").pathString) + module.checkSources( + root: "/mah/target/exe", + paths: swift.appending(components: "exe", "main.swift").pathString, + swift.appending(components: "exe", "foo.swift").pathString, + swift.appending(components: "bar.swift").pathString + ) } try package.checkModule("clib") { module in @@ -745,8 +774,9 @@ struct PackageBuilderTests { func testCustomTargetPathsOverlap() throws { let bar: AbsolutePath = "/target/bar" - let fs = InMemoryFileSystem(emptyFiles: - bar.appending(components: "bar.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + bar.appending(components: "bar.swift").pathString, bar.appending(components: "Tests", "barTests.swift").pathString ) @@ -755,11 +785,13 @@ struct PackageBuilderTests { targets: [ try TargetDescription( name: "bar", - path: "target/bar"), + path: "target/bar" + ), try TargetDescription( name: "barTests", path: "target/bar/Tests", - type: .test), + type: .test + ), ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -772,11 +804,13 @@ struct PackageBuilderTests { try TargetDescription( name: "bar", path: "target/bar", - exclude: ["Tests"]), + exclude: ["Tests"] + ), try TargetDescription( name: "barTests", path: "target/bar/Tests", - type: .test), + type: .test + ), ] ) try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -801,8 +835,9 @@ struct PackageBuilderTests { let Sources: AbsolutePath = "/Sources" let Tests: AbsolutePath = "/Tests" - let fs = InMemoryFileSystem(emptyFiles: - Sources.appending(components: "Foo", "inc", "module.modulemap").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + Sources.appending(components: "Foo", "inc", "module.modulemap").pathString, Sources.appending(components: "Foo", "inc", "Foo.h").pathString, Sources.appending(components: "Foo", "Foo_private.h").pathString, Sources.appending(components: "Foo", "Foo.c").pathString, @@ -816,9 +851,11 @@ struct PackageBuilderTests { targets: [ try TargetDescription( name: "Foo", - publicHeadersPath: "inc"), + publicHeadersPath: "inc" + ), try TargetDescription( - name: "Bar"), + name: "Bar" + ), ] ) @@ -827,7 +864,7 @@ struct PackageBuilderTests { try package.checkModule("Foo") { module in let clangTarget = try #require(module.target as? ClangModule) - #expect(clangTarget.headers.map{ $0.pathString } == [Sources.appending(components: "Foo", "Foo_private.h").pathString, Sources.appending(components: "Foo", "inc", "Foo.h").pathString]) + #expect(clangTarget.headers.map { $0.pathString } == [Sources.appending(components: "Foo", "Foo_private.h").pathString, Sources.appending(components: "Foo", "inc", "Foo.h").pathString]) module.check(c99name: "Foo", type: .library) module.checkSources(root: Sources.appending(components: "Foo").pathString, paths: "Foo.c") module.check(includeDir: Sources.appending(components: "Foo", "inc").pathString) @@ -845,8 +882,9 @@ struct PackageBuilderTests { @Test func testInvalidPublicHeadersPath() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/Foo/inc/module.modulemap", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/Foo/inc/module.modulemap", "/Sources/Foo/inc/Foo.h", "/Sources/Foo/Foo.c", "/Sources/Bar/include/module.modulemap", @@ -859,9 +897,11 @@ struct PackageBuilderTests { targets: [ try TargetDescription( name: "Foo", - publicHeadersPath: "/inc"), + publicHeadersPath: "/inc" + ), try TargetDescription( - name: "Bar"), + name: "Bar" + ), ] ) @@ -874,8 +914,9 @@ struct PackageBuilderTests { func testTestsLayoutsv4() throws { let Sources: AbsolutePath = "/Sources" - let fs = InMemoryFileSystem(emptyFiles: - Sources.appending(components: "A", "main.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + Sources.appending(components: "A", "main.swift").pathString, "/Tests/B/Foo.swift", "/Tests/ATests/Foo.swift", "/Tests/TheTestOfA/Foo.swift" @@ -923,8 +964,9 @@ struct PackageBuilderTests { @Test func testMultipleTestProducts() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/foo/foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/foo/foo.swift", "/Tests/fooTests/foo.swift", "/Tests/barTests/bar.swift" ) @@ -962,10 +1004,12 @@ struct PackageBuilderTests { @Test func testCustomTargetDependencies() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/Foo/Foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/Foo/Foo.swift", "/Sources/Bar/Bar.swift", - "/Sources/Baz/Baz.swift") + "/Sources/Baz/Baz.swift" + ) // Direct. var manifest = Manifest.createRootManifest( @@ -1024,8 +1068,9 @@ struct PackageBuilderTests { func testTargetDependencies() throws { let Sources: AbsolutePath = "/Sources" - let fs = InMemoryFileSystem(emptyFiles: - Sources.appending(components: "Foo", "Foo.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + Sources.appending(components: "Foo", "Foo.swift").pathString, Sources.appending(components: "Bar", "Bar.swift").pathString, Sources.appending(components: "Baz", "Baz.swift").pathString ) @@ -1037,7 +1082,8 @@ struct PackageBuilderTests { try TargetDescription(name: "Baz"), try TargetDescription( name: "Foo", - dependencies: ["Bar", "Baz", "Bam"]), + dependencies: ["Bar", "Baz", "Bam"] + ), ] ) try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -1067,17 +1113,18 @@ struct PackageBuilderTests { let predefinedSourceDir = PackageBuilder.suggestedPredefinedSourceDirectory(type: .regular) do { // Single target: Sources are expected in ./Sources. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Foo.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random"), + try TargetDescription(name: "Random") ] ) - + try PackageBuilderTester(manifest, in: fs) { package, diagnostics in try package.checkModule("Random") { result in #expect("/\(predefinedSourceDir)" == result.target.path) @@ -1089,14 +1136,15 @@ struct PackageBuilderTests { // In this case, there is a stray source file at the top-level, and no sources // under ./Sources, so the target Random has no sources. // This results in a *warning* that there are no sources for the target. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random"), + try TargetDescription(name: "Random") ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1106,15 +1154,16 @@ struct PackageBuilderTests { do { // Single target: Sources are expected in ./Sources. In this case, // there is a stray source file at the top-level which is ignored. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift", "/\(predefinedSourceDir)/Random.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random"), + try TargetDescription(name: "Random") ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -1125,15 +1174,16 @@ struct PackageBuilderTests { // Single target: Sources can be expected in ./Sources/. // If that directory exists, stray sources inside ./Sources will // not be included in the target. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Stray.swift", "/\(predefinedSourceDir)/Random/Random.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random"), + try TargetDescription(name: "Random") ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -1145,8 +1195,9 @@ struct PackageBuilderTests { do { // Multiple targets: Sources are expected in their respective subdirectories // under Sources - let fs = InMemoryFileSystem(emptyFiles: - "/Foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Foo.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", @@ -1167,17 +1218,18 @@ struct PackageBuilderTests { let predefinedSourceDir = PackageBuilder.suggestedPredefinedSourceDirectory(type: .test) do { // Single target: Sources are expected in ./Sources. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Foo.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "MyTests", type: .test), + try TargetDescription(name: "MyTests", type: .test) ] ) - + try PackageBuilderTester(manifest, in: fs) { package, diagnostics in try package.checkModule("MyTests") { result in #expect("/\(predefinedSourceDir)" == result.target.path) @@ -1190,14 +1242,15 @@ struct PackageBuilderTests { // In this case, there is a stray source file at the top-level, and no sources // under ./Tests, so the target RandomTests has no sources. // This results in a *warning* that there are no sources for the target. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "RandomTests", type: .test), + try TargetDescription(name: "RandomTests", type: .test) ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1207,15 +1260,16 @@ struct PackageBuilderTests { do { // Single target: Sources are expected in ./Tests. In this case, // there is a stray source file at the top-level which is ignored. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift", "/\(predefinedSourceDir)/RandomTests.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "RandomTests", type: .test), + try TargetDescription(name: "RandomTests", type: .test) ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -1227,15 +1281,16 @@ struct PackageBuilderTests { // Single target: Sources can be expected in ./Tests/. // If that directory exists, stray sources inside ./Tests will // not be included in the target. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Stray.swift", "/\(predefinedSourceDir)/RandomTests/Random.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "RandomTests", type: .test), + try TargetDescription(name: "RandomTests", type: .test) ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -1248,8 +1303,9 @@ struct PackageBuilderTests { do { // Multiple targets: Sources are expected in their respective subdirectories // under Sources - let fs = InMemoryFileSystem(emptyFiles: - "/Foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Foo.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", @@ -1270,17 +1326,18 @@ struct PackageBuilderTests { let predefinedSourceDir = PackageBuilder.suggestedPredefinedSourceDirectory(type: .plugin) do { // Single target: Sources are expected in ./Sources. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Foo.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "MyPlugin", type: .plugin, pluginCapability: .buildTool), + try TargetDescription(name: "MyPlugin", type: .plugin, pluginCapability: .buildTool) ] ) - + try PackageBuilderTester(manifest, in: fs) { package, diagnostics in try package.checkModule("MyPlugin") { result in result.checkSources(root: result.target.path.appending(component: predefinedSourceDir).pathString, paths: "Foo.swift") @@ -1292,14 +1349,15 @@ struct PackageBuilderTests { // In this case, there is a stray source file at the top-level, and no sources // under ./Plugins, so the target Random has no sources. // This results in a *warning* that there are no sources for the target. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random", type: .plugin, pluginCapability: .buildTool), + try TargetDescription(name: "Random", type: .plugin, pluginCapability: .buildTool) ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1310,15 +1368,16 @@ struct PackageBuilderTests { do { // Single target: Sources are expected in ./Plugins. In this case, // there is a stray source file at the top-level which is ignored. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift", "/\(predefinedSourceDir)/Random.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random", type: .plugin, pluginCapability: .buildTool), + try TargetDescription(name: "Random", type: .plugin, pluginCapability: .buildTool) ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -1329,15 +1388,16 @@ struct PackageBuilderTests { // Single target: Sources can be expected in ./Plugins/. // If that directory exists, stray sources inside ./Plugins will // not be included in the target. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Stray.swift", "/\(predefinedSourceDir)/Random/Random.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random", type: .plugin, pluginCapability: .buildTool), + try TargetDescription(name: "Random", type: .plugin, pluginCapability: .buildTool) ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -1349,8 +1409,9 @@ struct PackageBuilderTests { do { // Multiple targets: Sources are expected in their respective subdirectories // under Sources - let fs = InMemoryFileSystem(emptyFiles: - "/Foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Foo.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", @@ -1371,14 +1432,15 @@ struct PackageBuilderTests { let predefinedSourceDir = PackageBuilder.suggestedPredefinedSourceDirectory(type: .executable) do { // Single target: Sources are expected in ./Sources. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Foo.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "MyExe", type: .executable), + try TargetDescription(name: "MyExe", type: .executable) ] ) @@ -1394,14 +1456,15 @@ struct PackageBuilderTests { // In this case, there is a stray source file at the top-level, and no sources // under ./Sources, so the target Random has no sources. // This results in a *warning* that there are no sources for the target. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random", type: .executable), + try TargetDescription(name: "Random", type: .executable) ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1411,8 +1474,9 @@ struct PackageBuilderTests { do { // Single target: Sources are expected in ./Sources. In this case, // there is a stray source file at the top-level which is ignored. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift", "/\(predefinedSourceDir)/Random.swift" ) let manifest = Manifest.createRootManifest( @@ -1431,8 +1495,9 @@ struct PackageBuilderTests { // Single target: Sources can be expected in ./Sources/. // If that directory exists, stray sources inside ./Sources will // not be included in the target. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Stray.swift", "/\(predefinedSourceDir)/Random/Random.swift" ) let manifest = Manifest.createRootManifest( @@ -1452,15 +1517,16 @@ struct PackageBuilderTests { do { // Multiple targets: Sources are expected in their respective subdirectories // under Sources - let fs = InMemoryFileSystem(emptyFiles: - "/Foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Foo.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ try TargetDescription(name: "TargetA", type: .executable), - try TargetDescription(name: "TargetB", type: .executable) + try TargetDescription(name: "TargetB", type: .executable), ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1474,14 +1540,15 @@ struct PackageBuilderTests { let predefinedSourceDir = PackageBuilder.suggestedPredefinedSourceDirectory(type: .system) do { // Single target: Sources are expected in ./Sources. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/module.modulemap" + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/module.modulemap" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Foo", type: .system), + try TargetDescription(name: "Foo", type: .system) ] ) @@ -1496,31 +1563,33 @@ struct PackageBuilderTests { // In this case, there is a stray source file at the top-level, and no sources // under ./Sources, so the target Random has no sources. // This results in a *warning* that there are no sources for the target. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random", type: .system), + try TargetDescription(name: "Random", type: .system) ] ) let map = "/\(predefinedSourceDir)/module.modulemap" try PackageBuilderTester(manifest, in: fs) { _, diagnostics in -#if _runtime(_ObjC) - diagnostics.check(diagnostic: "package has unsupported layout; missing system target module map at '\(map)'", severity: .error) -#else - // FIXME: there is a memory leak here - diagnostics.check(diagnostic: "package has unsupported layout; missing system target module map at '\(String(cString: map.fileSystemRepresentation))'", severity: .error) -#endif + #if _runtime(_ObjC) + diagnostics.check(diagnostic: "package has unsupported layout; missing system target module map at '\(map)'", severity: .error) + #else + // FIXME: there is a memory leak here + diagnostics.check(diagnostic: "package has unsupported layout; missing system target module map at '\(String(cString: map.fileSystemRepresentation))'", severity: .error) + #endif } } do { // Single target: Sources are expected in ./Sources. In this case, // there is a stray source file at the top-level which is ignored. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift", "/\(predefinedSourceDir)/module.modulemap" ) let manifest = Manifest.createRootManifest( @@ -1538,8 +1607,9 @@ struct PackageBuilderTests { // Single target: Sources can be expected in ./Sources/. // If that directory exists, stray sources inside ./Sources will // not be included in the target. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Stray.swift", "/\(predefinedSourceDir)/module.modulemap" ) let manifest = Manifest.createRootManifest( @@ -1558,15 +1628,17 @@ struct PackageBuilderTests { do { // Multiple targets: Sources are expected in their respective subdirectories // under Sources - let fs = InMemoryFileSystem(emptyFiles: - "/Foo.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Foo.swift" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ try TargetDescription(name: "TargetA", type: .system), - try TargetDescription(name: "TargetB", type: .system) + try TargetDescription(name: "TargetB", type: .system), ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1580,15 +1652,16 @@ struct PackageBuilderTests { let predefinedSourceDir = PackageBuilder.suggestedPredefinedSourceDirectory(type: .macro) do { // Single target: Sources are expected in ./Sources. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Foo.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Foo", type: .macro), + try TargetDescription(name: "Foo", type: .macro) ] ) @@ -1604,14 +1677,16 @@ struct PackageBuilderTests { // In this case, there is a stray source file at the top-level, and no sources // under ./Sources, so the target Random has no sources. // This results in a *warning* that there are no sources for the target. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Random", type: .macro), + try TargetDescription(name: "Random", type: .macro) ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1621,9 +1696,11 @@ struct PackageBuilderTests { do { // Single target: Sources are expected in ./Sources. In this case, // there is a stray source file at the top-level which is ignored. - let fs = InMemoryFileSystem(emptyFiles: - "/Stray.swift", - "/\(predefinedSourceDir)/Random.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Stray.swift", + "/\(predefinedSourceDir)/Random.swift" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", @@ -1643,8 +1720,9 @@ struct PackageBuilderTests { // Single target: Sources can be expected in ./Sources/. // If that directory exists, stray sources inside ./Sources will // not be included in the target. - let fs = InMemoryFileSystem(emptyFiles: - "/\(predefinedSourceDir)/Stray.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/\(predefinedSourceDir)/Stray.swift", "/\(predefinedSourceDir)/Random/Random.swift" ) let manifest = Manifest.createRootManifest( @@ -1664,15 +1742,17 @@ struct PackageBuilderTests { do { // Multiple targets: Sources are expected in their respective subdirectories // under Sources - let fs = InMemoryFileSystem(emptyFiles: - "/Foo.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Foo.swift" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", toolsVersion: .v5_9, targets: [ try TargetDescription(name: "TargetA", type: .macro), - try TargetDescription(name: "TargetB", type: .macro) + try TargetDescription(name: "TargetB", type: .macro), ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1685,18 +1765,24 @@ struct PackageBuilderTests { func testStrictSourceLocationPre5_9() throws { do { for fs in [ - InMemoryFileSystem(emptyFiles: - "/Sources/Foo.swift"), - InMemoryFileSystem(emptyFiles: - "/Stray.swift"), - InMemoryFileSystem(emptyFiles: - "/Stray.swift", - "/Sources/Random.swift"), + InMemoryFileSystem( + emptyFiles: + "/Sources/Foo.swift" + ), + InMemoryFileSystem( + emptyFiles: + "/Stray.swift" + ), + InMemoryFileSystem( + emptyFiles: + "/Stray.swift", + "/Sources/Random.swift" + ), ] { let manifest = Manifest.createRootManifest( displayName: "pkg", targets: [ - try TargetDescription(name: "Random"), + try TargetDescription(name: "Random") ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1709,13 +1795,15 @@ struct PackageBuilderTests { @Test func testManifestTargetDeclErrors() throws { do { - let fs = InMemoryFileSystem(emptyFiles: - "/src/pkg/Foo.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/src/pkg/Foo.swift" + ) // Reference an invalid dependency. let manifest = Manifest.createRootManifest( displayName: "pkg", targets: [ - try TargetDescription(name: "pkg", dependencies: [.target(name: "Foo")]), + try TargetDescription(name: "pkg", dependencies: [.target(name: "Foo")]) ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1724,8 +1812,10 @@ struct PackageBuilderTests { } do { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/pkg/Foo.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/pkg/Foo.swift" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", targets: [ @@ -1739,13 +1829,15 @@ struct PackageBuilderTests { } do { - let fs = InMemoryFileSystem(emptyFiles: - "/Source/pkg/Foo.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Source/pkg/Foo.swift" + ) // Reference self in dependencies. let manifest = Manifest.createRootManifest( displayName: "pkg", targets: [ - try TargetDescription(name: "pkg", dependencies: [.target(name: "pkg")]), + try TargetDescription(name: "pkg", dependencies: [.target(name: "pkg")]) ], traits: [] ) @@ -1761,7 +1853,7 @@ struct PackageBuilderTests { displayName: "pkg", targets: [ try TargetDescription(name: "foo", url: "https://foo.com/foo.zip", type: .binary, checksum: "checksum"), - try TargetDescription(name: "foo2", path: "./foo2.zip", type: .binary) + try TargetDescription(name: "foo2", path: "./foo2.zip", type: .binary), ] ) @@ -1769,7 +1861,7 @@ struct PackageBuilderTests { let binaryArtifacts = [ "foo": BinaryArtifact(kind: .xcframework, originURL: "https://foo.com/foo.zip", path: "/foo.xcframework"), - "foo2": BinaryArtifact(kind: .xcframework, originURL: nil, path: "/foo2.xcframework") + "foo2": BinaryArtifact(kind: .xcframework, originURL: nil, path: "/foo2.xcframework"), ] try PackageBuilderTester(manifest, binaryArtifacts: binaryArtifacts, in: fs) { package, _ in try package.checkModule("foo") @@ -1778,8 +1870,9 @@ struct PackageBuilderTests { } do { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/pkg1/Foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/pkg1/Foo.swift", "/Sources/pkg2/Foo.swift", "/Sources/pkg3/Foo.swift" ) @@ -1813,8 +1906,9 @@ struct PackageBuilderTests { let pkg2: AbsolutePath = "/Sources/pkg2" // Reference a target which doesn't have sources. - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/pkg1/Foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/pkg1/Foo.swift", pkg2.appending(components: "readme.txt").pathString ) @@ -1838,14 +1932,16 @@ struct PackageBuilderTests { } do { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/Foo/Foo.c", - "/Sources/Bar/Bar.c") + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/Foo/Foo.c", + "/Sources/Bar/Bar.c" + ) var manifest = Manifest.createRootManifest( displayName: "Foo", targets: [ - try TargetDescription(name: "Foo", publicHeadersPath: "../inc"), + try TargetDescription(name: "Foo", publicHeadersPath: "../inc") ] ) @@ -1856,7 +1952,7 @@ struct PackageBuilderTests { manifest = Manifest.createRootManifest( displayName: "Foo", targets: [ - try TargetDescription(name: "Bar", publicHeadersPath: "inc/../../../foo"), + try TargetDescription(name: "Bar", publicHeadersPath: "inc/../../../foo") ] ) try PackageBuilderTester(manifest, in: fs) { _, diagnostics in @@ -1865,14 +1961,16 @@ struct PackageBuilderTests { } do { - let fs = InMemoryFileSystem(emptyFiles: - "/pkg/Sources/Foo/Foo.c", - "/foo/Bar.c") + let fs = InMemoryFileSystem( + emptyFiles: + "/pkg/Sources/Foo/Foo.c", + "/foo/Bar.c" + ) let manifest = Manifest.createRootManifest( displayName: "Foo", targets: [ - try TargetDescription(name: "Foo", path: "../foo"), + try TargetDescription(name: "Foo", path: "../foo") ] ) try PackageBuilderTester(manifest, path: "/pkg", in: fs) { package, diagnostics in @@ -1880,14 +1978,16 @@ struct PackageBuilderTests { } } do { - let fs = InMemoryFileSystem(emptyFiles: - "/pkg/Sources/Foo/Foo.c", - "/foo/Bar.c") + let fs = InMemoryFileSystem( + emptyFiles: + "/pkg/Sources/Foo/Foo.c", + "/foo/Bar.c" + ) let manifest = Manifest.createRootManifest( displayName: "Foo", targets: [ - try TargetDescription(name: "Foo", path: "/foo"), + try TargetDescription(name: "Foo", path: "/foo") ] ) try PackageBuilderTester(manifest, path: "/pkg", in: fs) { _, diagnostics in @@ -1900,7 +2000,7 @@ struct PackageBuilderTests { let fs = InMemoryFileSystem(emptyFiles: "/pkg/Sources/Foo/Foo.c", "/foo/Bar.c") - + let manifest = Manifest.createRootManifest( displayName: "Foo", targets: [ @@ -1916,9 +2016,11 @@ struct PackageBuilderTests { @Test func testExecutableAsADep() throws { // Executable as dependency. - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/exec/main.swift", - "/Sources/lib/lib.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/exec/main.swift", + "/Sources/lib/lib.swift" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", @@ -1944,8 +2046,9 @@ struct PackageBuilderTests { @Test func testInvalidManifestConfigForNonSystemModules() throws { - var fs = InMemoryFileSystem(emptyFiles: - "/Sources/main.swift" + var fs = InMemoryFileSystem( + emptyFiles: + "/Sources/main.swift" ) var manifest = Manifest.createRootManifest( @@ -1956,11 +2059,13 @@ struct PackageBuilderTests { try PackageBuilderTester(manifest, in: fs) { package, diagnostics in diagnostics.check( diagnostic: "configuration of package '\(package.packageIdentity)' is invalid; the 'pkgConfig' property can only be used with a System Module Package", - severity: .error) + severity: .error + ) } - fs = InMemoryFileSystem(emptyFiles: - "/Sources/Foo/main.c" + fs = InMemoryFileSystem( + emptyFiles: + "/Sources/Foo/main.c" ) manifest = Manifest.createRootManifest( displayName: "pkg", @@ -1970,14 +2075,17 @@ struct PackageBuilderTests { try PackageBuilderTester(manifest, in: fs) { package, diagnostics in diagnostics.check( diagnostic: "configuration of package '\(package.packageIdentity)' is invalid; the 'providers' property can only be used with a System Module Package", - severity: .error) + severity: .error + ) } } @Test func testResolvesSystemModulePackage() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/module.modulemap") + let fs = InMemoryFileSystem( + emptyFiles: + "/module.modulemap" + ) let manifest = Manifest.createRootManifest(displayName: "SystemModulePackage") try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -1991,8 +2099,9 @@ struct PackageBuilderTests { @Test func testCompatibleSwiftVersions() throws { // Single swift executable target. - let fs = InMemoryFileSystem(emptyFiles: - "/foo/main.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/foo/main.swift" ) func createManifest(swiftVersions: [SwiftLanguageVersion]?) throws -> Manifest { @@ -2000,7 +2109,7 @@ struct PackageBuilderTests { displayName: "pkg", swiftLanguageVersions: swiftVersions, targets: [ - try TargetDescription(name: "foo", path: "foo"), + try TargetDescription(name: "foo", path: "foo") ] ) } @@ -2076,9 +2185,11 @@ struct PackageBuilderTests { do { // We should look only in one of the predefined search paths. - let fs = InMemoryFileSystem(emptyFiles: - "/Source/Foo/Foo.swift", - "/src/Bar/Bar.swift") + let fs = InMemoryFileSystem( + emptyFiles: + "/Source/Foo/Foo.swift", + "/src/Bar/Bar.swift" + ) let manifest = Manifest.createRootManifest( displayName: "pkg", @@ -2095,10 +2206,12 @@ struct PackageBuilderTests { do { // We should look only in one of the predefined search paths. - let fs = InMemoryFileSystem(emptyFiles: - "/Source/Foo/Foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Source/Foo/Foo.swift", "/Tests/FooTests/Foo.swift", - "/Source/BarTests/Foo.swift") + "/Source/BarTests/Foo.swift" + ) var manifest = Manifest.createRootManifest( displayName: "pkg", @@ -2151,8 +2264,9 @@ struct PackageBuilderTests { func testSpecialTargetDir() throws { let src: AbsolutePath = "/src" // Special directory should be src because both target and test target are under it. - let fs = InMemoryFileSystem(emptyFiles: - src.appending(components: "A", "Foo.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + src.appending(components: "A", "Foo.swift").pathString, src.appending(components: "ATests", "Foo.swift").pathString ) @@ -2181,8 +2295,9 @@ struct PackageBuilderTests { @Test func testExcludes() throws { // The exclude should win if a file is in exclude as well as sources. - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/bar/barExcluded.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/bar/barExcluded.swift", "/Sources/bar/bar.swift" ) @@ -2191,9 +2306,9 @@ struct PackageBuilderTests { targets: [ try TargetDescription( name: "bar", - exclude: ["barExcluded.swift",], + exclude: ["barExcluded.swift"], sources: ["bar.swift", "barExcluded.swift"] - ), + ) ] ) try PackageBuilderTester(manifest, in: fs) { package, _ in @@ -2208,8 +2323,9 @@ struct PackageBuilderTests { func testDuplicateProducts() throws { // Check that declaring executable product doesn't collide with the // inferred products. - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/foo/foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/foo/foo.swift" ) let manifest = Manifest.createRootManifest( @@ -2221,7 +2337,7 @@ struct PackageBuilderTests { try ProductDescription(name: "foo-dy", type: .library(.dynamic), targets: ["foo"]), ], targets: [ - try TargetDescription(name: "foo"), + try TargetDescription(name: "foo") ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -2245,8 +2361,9 @@ struct PackageBuilderTests { @Test func testSystemPackageDeclaresTargetsDiagnostic() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/module.modulemap", + let fs = InMemoryFileSystem( + emptyFiles: + "/module.modulemap", "/Sources/foo/main.swift", "/Sources/bar/main.swift" ) @@ -2272,15 +2389,16 @@ struct PackageBuilderTests { @Test func testSystemLibraryTarget() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/foo/module.modulemap", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/foo/module.modulemap", "/Sources/bar/bar.swift" ) let manifest = Manifest.createRootManifest( displayName: "pkg", products: [ - try ProductDescription(name: "foo", type: .library(.automatic), targets: ["foo"]), + try ProductDescription(name: "foo", type: .library(.automatic), targets: ["foo"]) ], targets: [ try TargetDescription(name: "foo", type: .system), @@ -2307,15 +2425,16 @@ struct PackageBuilderTests { func testSystemLibraryTargetDiagnostics() throws { let Sources: AbsolutePath = "/Sources" - let fs = InMemoryFileSystem(emptyFiles: - Sources.appending(components: "foo", "module.modulemap").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + Sources.appending(components: "foo", "module.modulemap").pathString, Sources.appending(components: "bar", "bar.swift").pathString ) var manifest = Manifest.createRootManifest( displayName: "SystemModulePackage", products: [ - try ProductDescription(name: "foo", type: .library(.automatic), targets: ["foo", "bar"]), + try ProductDescription(name: "foo", type: .library(.automatic), targets: ["foo", "bar"]) ], targets: [ try TargetDescription(name: "foo", type: .system), @@ -2334,7 +2453,7 @@ struct PackageBuilderTests { manifest = Manifest.createRootManifest( displayName: "SystemModulePackage", products: [ - try ProductDescription(name: "foo", type: .library(.static), targets: ["foo"]), + try ProductDescription(name: "foo", type: .library(.static), targets: ["foo"]) ], targets: [ try TargetDescription(name: "foo", type: .system), @@ -2369,8 +2488,9 @@ struct PackageBuilderTests { @Test func testBadExecutableProductDecl() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/foo1/main.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/foo1/main.swift", "/Sources/foo2/main.swift", "/Sources/FooLib1/lib.swift", "/Sources/FooLib2/lib.swift", @@ -2383,7 +2503,7 @@ struct PackageBuilderTests { try ProductDescription(name: "foo1", type: .executable, targets: ["FooLib1"]), try ProductDescription(name: "foo2", type: .executable, targets: ["FooLib1", "FooLib2"]), try ProductDescription(name: "foo3", type: .executable, targets: ["foo1", "foo2"]), - try ProductDescription(name: "foo3", type: .executable, targets: ["foo1", "Plugin1"]) + try ProductDescription(name: "foo3", type: .executable, targets: ["foo1", "Plugin1"]), ], targets: [ try TargetDescription(name: "foo1"), @@ -2426,8 +2546,9 @@ struct PackageBuilderTests { @Test func testLibraryProductDiagnostics() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/MyLibrary/library.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/MyLibrary/library.swift", "/Plugins/MyPlugin/plugin.swift" ) @@ -2438,7 +2559,7 @@ struct PackageBuilderTests { ], targets: [ try TargetDescription(name: "MyLibrary", type: .regular), - try TargetDescription(name: "MyPlugin", type: .plugin, pluginCapability: .buildTool) + try TargetDescription(name: "MyPlugin", type: .plugin, pluginCapability: .buildTool), ] ) try PackageBuilderTester(manifest, in: fs) { package, diagnostics in @@ -2453,17 +2574,17 @@ struct PackageBuilderTests { } } - @Test func testBadREPLPackage() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/exe/main.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/exe/main.swift" ) let manifest = Manifest.createRootManifest( displayName: "Pkg", targets: [ - try TargetDescription(name: "exe"), + try TargetDescription(name: "exe") ] ) @@ -2480,8 +2601,9 @@ struct PackageBuilderTests { @Test func testAsmIsIgnoredInV4_2Manifest() throws { // .s is not considered a valid source in 4.2 manifest. - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/lib/lib.s", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/lib/lib.s", "/Sources/lib/lib2.S", "/Sources/lib/lib.c", "/Sources/lib/include/lib.h" @@ -2491,7 +2613,7 @@ struct PackageBuilderTests { displayName: "pkg", toolsVersion: .v4_2, targets: [ - try TargetDescription(name: "lib", dependencies: []), + try TargetDescription(name: "lib", dependencies: []) ] ) @@ -2504,8 +2626,9 @@ struct PackageBuilderTests { @Test func testAsmInV5Manifest() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/lib/lib.s", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/lib/lib.s", "/Sources/lib/lib2.S", "/Sources/lib/lib.c", "/Sources/lib/include/lib.h" @@ -2515,7 +2638,7 @@ struct PackageBuilderTests { displayName: "Pkg", toolsVersion: .v5, targets: [ - try TargetDescription(name: "lib", dependencies: []), + try TargetDescription(name: "lib", dependencies: []) ] ) @@ -2531,8 +2654,9 @@ struct PackageBuilderTests { let lib: AbsolutePath = "/Sources/lib" // Files with unknown suffixes under declared sources are not considered valid sources in 5.2 manifest. - let fs = InMemoryFileSystem(emptyFiles: - lib.appending(components: "movie.mkv").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + lib.appending(components: "movie.mkv").pathString, lib.appending(components: "lib.c").pathString, lib.appending(components: "include", "lib.h").pathString ) @@ -2541,7 +2665,7 @@ struct PackageBuilderTests { displayName: "pkg", toolsVersion: .v5_2, targets: [ - try TargetDescription(name: "lib", dependencies: [], path: "./Sources/lib", sources: ["."]), + try TargetDescription(name: "lib", dependencies: [], path: "./Sources/lib", sources: ["."]) ] ) @@ -2559,8 +2683,9 @@ struct PackageBuilderTests { let lib: AbsolutePath = "/Sources/lib" // Files with unknown suffixes under declared sources are treated as compilable in 5.3 manifest. - let fs = InMemoryFileSystem(emptyFiles: - lib.appending(components: "movie.mkv").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + lib.appending(components: "movie.mkv").pathString, lib.appending(components: "lib.c").pathString, lib.appending(components: "include", "lib.h").pathString ) @@ -2569,7 +2694,7 @@ struct PackageBuilderTests { displayName: "pkg", toolsVersion: .v5_3, targets: [ - try TargetDescription(name: "lib", dependencies: [], path: "./Sources/lib", sources: ["."]), + try TargetDescription(name: "lib", dependencies: [], path: "./Sources/lib", sources: ["."]) ] ) @@ -2584,8 +2709,9 @@ struct PackageBuilderTests { @Test func testBuildSettings() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/exe/main.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/exe/main.swift", "/Sources/bar/bar.swift", "/Sources/cbar/barcpp.cpp", "/Sources/cbar/bar.c", @@ -2611,7 +2737,8 @@ struct PackageBuilderTests { ] ), try TargetDescription( - name: "bar", dependencies: ["foo"], + name: "bar", + dependencies: ["foo"], settings: [ .init(tool: .swift, kind: .define("SOMETHING")), .init(tool: .swift, kind: .define("LINUX"), condition: .init(platformNames: ["linux"])), @@ -2621,7 +2748,8 @@ struct PackageBuilderTests { ] ), try TargetDescription( - name: "exe", dependencies: ["bar"], + name: "exe", + dependencies: ["bar"], settings: [ .init(tool: .linker, kind: .linkedLibrary("sqlite3")), .init(tool: .linker, kind: .linkedFramework("CoreData"), condition: .init(platformNames: ["ios"])), @@ -2697,8 +2825,9 @@ struct PackageBuilderTests { @Test func testEmptyUnsafeFlagsAreAllowed() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/foo/foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/foo/foo.swift", "/Sources/bar/bar.cpp", "/Sources/bar/bar.c", "/Sources/bar/include/bar.h" @@ -2774,8 +2903,9 @@ struct PackageBuilderTests { @Test func testInvalidHeaderSearchPath() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/pkg/Sources/exe/main.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/pkg/Sources/exe/main.swift" ) let manifest1 = Manifest.createRootManifest( @@ -2785,9 +2915,9 @@ struct PackageBuilderTests { try TargetDescription( name: "exe", settings: [ - .init(tool: .c, kind: .headerSearchPath("/Sources/headers")), + .init(tool: .c, kind: .headerSearchPath("/Sources/headers")) ] - ), + ) ] ) @@ -2802,9 +2932,9 @@ struct PackageBuilderTests { try TargetDescription( name: "exe", settings: [ - .init(tool: .c, kind: .headerSearchPath("../../..")), + .init(tool: .c, kind: .headerSearchPath("../../..")) ] - ), + ) ] ) @@ -2815,8 +2945,9 @@ struct PackageBuilderTests { @Test func testDuplicateTargetDependencies() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Foo/Sources/Foo/foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Foo/Sources/Foo/foo.swift", "/Foo/Sources/Foo2/foo.swift", "/Foo/Sources/Foo3/foo.swift", "/Foo/Sources/Qux/foo.swift", @@ -2829,7 +2960,7 @@ struct PackageBuilderTests { displayName: "Foo", toolsVersion: .v5, dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], targets: [ try TargetDescription( @@ -2838,26 +2969,27 @@ struct PackageBuilderTests { // invalid - same target in package "Bar" "Bar", "Bar", - + // invalid - same target in package "Bar" "Bar2", .product(name: "Bar2", package: "Bar"), - + // invalid - same target in this package "Foo2", "Foo2", - + // invalid - same target in this package "Foo3", .target(name: "Foo3"), - + // valid - different packages "Qux", - .product(name: "Qux", package: "Bar") - ]), + .product(name: "Qux", package: "Bar"), + ] + ), try TargetDescription(name: "Foo2"), try TargetDescription(name: "Foo3"), - try TargetDescription(name: "Qux") + try TargetDescription(name: "Qux"), ], traits: [] ) @@ -2888,8 +3020,9 @@ struct PackageBuilderTests { @Test func testConditionalDependencies() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/Foo/main.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/Foo/main.swift", "/Sources/Bar/bar.swift", "/Sources/Baz/baz.swift" ) @@ -2898,24 +3031,34 @@ struct PackageBuilderTests { displayName: "Foo", toolsVersion: .v5, dependencies: [ - .fileSystem(path: "/Biz"), + .fileSystem(path: "/Biz") ], targets: [ try TargetDescription( name: "Foo", dependencies: [ - .target(name: "Bar", condition: PackageConditionDescription( - platformNames: ["macos"], - config: nil - )), - .byName(name: "Baz", condition: PackageConditionDescription( - platformNames: [], - config: "debug" - )), - .product(name: "Biz", package: "Biz", condition: PackageConditionDescription( - platformNames: ["watchos", "ios"], - config: "release" - )), + .target( + name: "Bar", + condition: PackageConditionDescription( + platformNames: ["macos"], + config: nil + ) + ), + .byName( + name: "Baz", + condition: PackageConditionDescription( + platformNames: [], + config: "debug" + ) + ), + .product( + name: "Biz", + package: "Biz", + condition: PackageConditionDescription( + platformNames: ["watchos", "ios"], + config: "release" + ) + ), ] ), try TargetDescription(name: "Bar"), @@ -2955,8 +3098,9 @@ struct PackageBuilderTests { @Test func testMissingDefaultLocalization() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Foo/Sources/Foo/foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Foo/Sources/Foo/foo.swift", "/Foo/Sources/Foo/Resources/en.lproj/Localizable.strings" ) @@ -2964,9 +3108,12 @@ struct PackageBuilderTests { displayName: "Foo", toolsVersion: .v5_3, targets: [ - try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "Resources") - ]), + try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "Resources") + ] + ) ] ) @@ -2979,12 +3126,13 @@ struct PackageBuilderTests { func testXcodeResources5_4AndEarlier() throws { // In SwiftTools 5.4 and earlier, supported xcbuild file types are supported by default. // Of course, modern file types such as xcstrings won't be supported here because those require a newer Swift tools version in general. - + let root: AbsolutePath = "/Foo" let foo = root.appending(components: "Sources", "Foo") - let fs = InMemoryFileSystem(emptyFiles: - foo.appending(components: "foo.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + foo.appending(components: "foo.swift").pathString, foo.appending(components: "Foo.xcassets").pathString, foo.appending(components: "Foo.xib").pathString, foo.appending(components: "Foo.xcdatamodel").pathString, @@ -2995,7 +3143,7 @@ struct PackageBuilderTests { displayName: "Foo", toolsVersion: .v5_3, targets: [ - try TargetDescription(name: "Foo"), + try TargetDescription(name: "Foo") ] ) @@ -3006,21 +3154,22 @@ struct PackageBuilderTests { foo.appending(components: "Foo.xib").pathString, foo.appending(components: "Foo.xcdatamodel").pathString, foo.appending(components: "Foo.xcassets").pathString, - foo.appending(components: "Foo.metal").pathString + foo.appending(components: "Foo.metal").pathString, ]) } } } - + @Test func testXcodeResources5_5AndLater() throws { // In SwiftTools 5.5 and later, xcbuild file types are only supported when explicitly passed via additionalFileRules. - + let root: AbsolutePath = "/Foo" let foo = root.appending(components: "Sources", "Foo") - let fs = InMemoryFileSystem(emptyFiles: - foo.appending(components: "foo.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + foo.appending(components: "foo.swift").pathString, foo.appending(components: "Foo.xcassets").pathString, foo.appending(components: "Foo.xcstrings").pathString, foo.appending(components: "Foo.xib").pathString, @@ -3032,7 +3181,7 @@ struct PackageBuilderTests { displayName: "Foo", toolsVersion: .v5_9, targets: [ - try TargetDescription(name: "Foo"), + try TargetDescription(name: "Foo") ] ) @@ -3044,7 +3193,7 @@ struct PackageBuilderTests { foo.appending(components: "Foo.xcdatamodel").pathString, foo.appending(components: "Foo.xcassets").pathString, foo.appending(components: "Foo.xcstrings").pathString, - foo.appending(components: "Foo.metal").pathString + foo.appending(components: "Foo.metal").pathString, ]) } } @@ -3057,8 +3206,9 @@ struct PackageBuilderTests { let root: AbsolutePath = "/Foo" let foo = root.appending(components: "Sources", "Foo") - let fs = InMemoryFileSystem(emptyFiles: - foo.appending(components: "foo.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + foo.appending(components: "foo.swift").pathString, foo.appending(components: "Foo.xcassets").pathString, foo.appending(components: "Foo.xcstrings").pathString, foo.appending(components: "Foo.xib").pathString, @@ -3071,7 +3221,7 @@ struct PackageBuilderTests { displayName: "Foo", toolsVersion: .v6_0, targets: [ - try TargetDescription(name: "Foo"), + try TargetDescription(name: "Foo") ] ) @@ -3098,8 +3248,9 @@ struct PackageBuilderTests { let root: AbsolutePath = "/Foo" let foo = root.appending(components: "Sources", "Foo") - let fs = InMemoryFileSystem(emptyFiles: - foo.appending(components: "foo.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + foo.appending(components: "foo.swift").pathString, foo.appending(components: "PrivacyInfo.xcprivacy").pathString ) @@ -3110,7 +3261,7 @@ struct PackageBuilderTests { try TargetDescription( name: "Foo", resources: [.init(rule: .copy, path: "PrivacyInfo.xcprivacy")] - ), + ) ] ) @@ -3118,7 +3269,7 @@ struct PackageBuilderTests { try result.checkModule("Foo") { result in result.checkSources(sources: ["foo.swift"]) result.checkResources(resources: [ - foo.appending(components: "PrivacyInfo.xcprivacy").pathString, + foo.appending(components: "PrivacyInfo.xcprivacy").pathString ]) } @@ -3136,21 +3287,25 @@ struct PackageBuilderTests { let internalSourcesDir = root.appending(components: "Sources", "Internal") let productSourcesDir = root.appending(components: "Sources", "Product") let snippetsDir = root.appending(components: "Snippets") - let fs = InMemoryFileSystem(emptyFiles: - internalSourcesDir.appending("Internal.swift").pathString, + let fs = InMemoryFileSystem( + emptyFiles: + internalSourcesDir.appending("Internal.swift").pathString, productSourcesDir.appending("Product.swift").pathString, - snippetsDir.appending("ASnippet.swift").pathString) - + snippetsDir.appending("ASnippet.swift").pathString + ) + let manifest = Manifest.createRootManifest( - displayName: "Foo", toolsVersion: .v5_7, + displayName: "Foo", + toolsVersion: .v5_7, products: [ try ProductDescription(name: "Product", type: .library(.automatic), targets: ["Product"]) ], targets: [ try TargetDescription(name: "Internal"), try TargetDescription(name: "Product"), - ]) - + ] + ) + try PackageBuilderTester(manifest, path: root, in: fs) { result, diagnostics in result.checkProduct("Product") { product in product.check(type: .library(.automatic), targets: ["Product"]) @@ -3182,7 +3337,7 @@ struct PackageBuilderTests { try TargetDescription( name: "Foo", settings: [ - .init(tool: .swift, kind: .define("YOLO"), condition: .init(platformNames: ["bestOS"])), + .init(tool: .swift, kind: .define("YOLO"), condition: .init(platformNames: ["bestOS"])) ] ) ] @@ -3209,8 +3364,9 @@ struct PackageBuilderTests { @Test func testSwiftLanguageVersionPerTarget() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/foo/foo.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/foo/foo.swift", "/Sources/bar/bar.swift" ) @@ -3228,7 +3384,7 @@ struct PackageBuilderTests { name: "bar", settings: [ .init(tool: .swift, kind: .swiftLanguageMode(.v3), condition: .init(platformNames: ["linux"])), - .init(tool: .swift, kind: .swiftLanguageMode(.v4), condition: .init(platformNames: ["macos"], config: "debug")) + .init(tool: .swift, kind: .swiftLanguageMode(.v4), condition: .init(platformNames: ["macos"], config: "debug")), ] ), ] @@ -3273,8 +3429,9 @@ struct PackageBuilderTests { @Test func testSwiftWarningControlFlags() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/foo/foo.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/foo/foo.swift" ) let manifest = Manifest.createRootManifest( @@ -3289,7 +3446,7 @@ struct PackageBuilderTests { .init(tool: .swift, kind: .treatWarning("DeprecatedDeclaration", .error), condition: .init(config: "release")), .init(tool: .swift, kind: .treatWarning("DeprecatedDeclaration", .warning), condition: .init(config: "debug")), ] - ), + ) ] ) @@ -3300,8 +3457,7 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .debug) ) #expect( - macosDebugScope.evaluate(.OTHER_SWIFT_FLAGS) == - ["-no-warnings-as-errors", "-Wwarning", "DeprecatedDeclaration"] + macosDebugScope.evaluate(.OTHER_SWIFT_FLAGS) == ["-no-warnings-as-errors", "-Wwarning", "DeprecatedDeclaration"] ) let macosReleaseScope = BuildSettings.Scope( @@ -3309,17 +3465,17 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .release) ) #expect( - macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS) == - ["-warnings-as-errors", "-Werror", "DeprecatedDeclaration"] + macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS) == ["-warnings-as-errors", "-Werror", "DeprecatedDeclaration"] ) } } } - + @Test func testCWarningControlFlags() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/cfoo/foo.c", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/cfoo/foo.c", "/Sources/cfoo/include/cfoo.h" ) @@ -3346,8 +3502,7 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .debug) ) #expect( - macosDebugScope.evaluate(.OTHER_CFLAGS) == - ["-Wno-error", "-Wno-error=deprecated-declarations"] + macosDebugScope.evaluate(.OTHER_CFLAGS) == ["-Wno-error", "-Wno-error=deprecated-declarations"] ) let macosReleaseScope = BuildSettings.Scope( @@ -3355,8 +3510,7 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .release) ) #expect( - macosReleaseScope.evaluate(.OTHER_CFLAGS) == - ["-Werror", "-Werror=deprecated-declarations"] + macosReleaseScope.evaluate(.OTHER_CFLAGS) == ["-Werror", "-Werror=deprecated-declarations"] ) } } @@ -3364,8 +3518,9 @@ struct PackageBuilderTests { @Test func testCXXWarningControlFlags() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/cxxfoo/foo.cpp", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/cxxfoo/foo.cpp", "/Sources/cxxfoo/include/cxxfoo.h" ) @@ -3381,7 +3536,7 @@ struct PackageBuilderTests { .init(tool: .cxx, kind: .treatWarning("deprecated-declarations", .error), condition: .init(config: "release")), .init(tool: .cxx, kind: .treatWarning("deprecated-declarations", .warning), condition: .init(config: "debug")), ] - ), + ) ] ) @@ -3392,8 +3547,7 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .debug) ) #expect( - macosDebugScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == - ["-Wno-error", "-Wno-error=deprecated-declarations"] + macosDebugScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == ["-Wno-error", "-Wno-error=deprecated-declarations"] ) let macosReleaseScope = BuildSettings.Scope( @@ -3401,8 +3555,7 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .release) ) #expect( - macosReleaseScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == - ["-Werror", "-Werror=deprecated-declarations"] + macosReleaseScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == ["-Werror", "-Werror=deprecated-declarations"] ) } } @@ -3410,8 +3563,9 @@ struct PackageBuilderTests { @Test func testCWarningEnableDisable() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/cfoo/foo.c", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/cfoo/foo.c", "/Sources/cfoo/include/cfoo.h" ) @@ -3436,8 +3590,7 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .debug) ) #expect( - macosDebugScope.evaluate(.OTHER_CFLAGS) == - ["-Wimplicit-fallthrough"] + macosDebugScope.evaluate(.OTHER_CFLAGS) == ["-Wimplicit-fallthrough"] ) let macosReleaseScope = BuildSettings.Scope( @@ -3445,8 +3598,7 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .release) ) #expect( - macosReleaseScope.evaluate(.OTHER_CFLAGS) == - ["-Wno-unused-parameter"] + macosReleaseScope.evaluate(.OTHER_CFLAGS) == ["-Wno-unused-parameter"] ) } } @@ -3454,8 +3606,9 @@ struct PackageBuilderTests { @Test func testCXXWarningEnableDisable() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/cxxfoo/foo.cpp", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/cxxfoo/foo.cpp", "/Sources/cxxfoo/include/cxxfoo.h" ) @@ -3480,8 +3633,7 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .debug) ) #expect( - macosDebugScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == - ["-Wimplicit-fallthrough"] + macosDebugScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == ["-Wimplicit-fallthrough"] ) let macosReleaseScope = BuildSettings.Scope( @@ -3489,8 +3641,7 @@ struct PackageBuilderTests { environment: BuildEnvironment(platform: .macOS, configuration: .release) ) #expect( - macosReleaseScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == - ["-Wno-unused-parameter"] + macosReleaseScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == ["-Wno-unused-parameter"] ) } } @@ -3498,8 +3649,9 @@ struct PackageBuilderTests { @Test func testDefaultIsolationPerTarget() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Sources/A/a.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Sources/A/a.swift", "/Sources/B/b.swift" ) @@ -3517,7 +3669,7 @@ struct PackageBuilderTests { name: "B", settings: [ .init(tool: .swift, kind: .defaultIsolation(.nonisolated), condition: .init(platformNames: ["linux"])), - .init(tool: .swift, kind: .defaultIsolation(.MainActor), condition: .init(platformNames: ["macos"], config: "debug")) + .init(tool: .swift, kind: .defaultIsolation(.MainActor), condition: .init(platformNames: ["macos"], config: "debug")), ] ), ] @@ -3560,8 +3712,7 @@ struct PackageBuilderTests { package.target.buildSettings, environment: BuildEnvironment(platform: .macOS, configuration: .release) ) - #expect(!macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS).contains("-default-isolation") || - !macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS).contains("MainActor")) + #expect(!macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS).contains("-default-isolation") || !macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS).contains("MainActor")) } } @@ -3659,7 +3810,7 @@ final class PackageBuilderTester { Issue.record("Expected package did not load \(self)", sourceLocation: sourceLocation) return } - guard let target = package.modules.first(where: {$0.name == name}) else { + guard let target = package.modules.first(where: { $0.name == name }) else { Issue.record("Module: \(name) not found", sourceLocation: sourceLocation) return } @@ -3672,7 +3823,7 @@ final class PackageBuilderTester { Issue.record("Expected package did not load \(self)", sourceLocation: sourceLocation) return } - let foundProducts = package.products.filter{$0.name == name} + let foundProducts = package.products.filter { $0.name == name } guard foundProducts.count == 1 else { Issue.record("Couldn't get the product: \(name). Found products \(foundProducts)", sourceLocation: sourceLocation) return @@ -3690,7 +3841,7 @@ final class PackageBuilderTester { func check(type: PackageModel.ProductType, targets: [String], sourceLocation: SourceLocation = #_sourceLocation) { #expect(product.type == type, sourceLocation: sourceLocation) - #expect(product.modules.map{$0.name}.sorted() == targets.sorted(), sourceLocation: sourceLocation) + #expect(product.modules.map { $0.name }.sorted() == targets.sorted(), sourceLocation: sourceLocation) } func check(testEntryPointPath: String?, sourceLocation: SourceLocation = #_sourceLocation) { @@ -3745,7 +3896,7 @@ final class PackageBuilderTester { } func checkResources(resources: [String], sourceLocation: SourceLocation = #_sourceLocation) { - #expect(Set(resources) == Set(self.target.resources.map{ $0.path.pathString }), "unexpected resource files in \(target.name)", sourceLocation: sourceLocation) + #expect(Set(resources) == Set(self.target.resources.map { $0.path.pathString }), "unexpected resource files in \(target.name)", sourceLocation: sourceLocation) } func check(targetDependencies depsToCheck: [String], sourceLocation: SourceLocation = #_sourceLocation) { @@ -3795,11 +3946,13 @@ final class PackageBuilderTester { Issue.record("\(target) is not a swift target", sourceLocation: sourceLocation) return } - guard let versionAssignments = swiftTarget.buildSettings.assignments[.SWIFT_VERSION]? - .filter { $0.conditions.isEmpty }.flatMap(\.values) else { - Issue.record("\(target) has no version assignments", sourceLocation: sourceLocation) - return - } + guard + let versionAssignments = swiftTarget.buildSettings.assignments[.SWIFT_VERSION]? + .filter { $0.conditions.isEmpty }.flatMap(\.values) + else { + Issue.record("\(target) has no version assignments", sourceLocation: sourceLocation) + return + } #expect(versionAssignments.contains(swiftVersion) != nil, sourceLocation: sourceLocation) } diff --git a/Tests/PackageLoadingTests/PkgConfigAllowlistTests.swift b/Tests/PackageLoadingTests/PkgConfigAllowlistTests.swift index cddac43b194..60625a29ebc 100644 --- a/Tests/PackageLoadingTests/PkgConfigAllowlistTests.swift +++ b/Tests/PackageLoadingTests/PkgConfigAllowlistTests.swift @@ -36,7 +36,7 @@ final class PkgConfigAllowlistTests: XCTestCase { } func testRemoveDefaultFlags() throws { - let cFlags = ["-I/usr/include", "-I", "/usr/include" , "-I", "/usr/include/Cellar/gtk+3/3.18.9/include/gtk-3.0", "-L/hello", "-I", "/usr/include"] + let cFlags = ["-I/usr/include", "-I", "/usr/include", "-I", "/usr/include/Cellar/gtk+3/3.18.9/include/gtk-3.0", "-L/hello", "-I", "/usr/include"] let libs = ["-L", "/usr/lib", "-L/usr/lib/Cellar/gtk+3/3.18.9/lib", "-L/usr/lib", "-L/usr/lib", "-lgtk-3", "-module-name", "-lcool", "ok", "name", "-L", "/usr/lib"] let result = try removeDefaultFlags(cFlags: cFlags, libs: libs) diff --git a/Tests/PackageLoadingTests/PkgConfigParserTests.swift b/Tests/PackageLoadingTests/PkgConfigParserTests.swift index cfdad79f4db..1bd42e6b067 100644 --- a/Tests/PackageLoadingTests/PkgConfigParserTests.swift +++ b/Tests/PackageLoadingTests/PkgConfigParserTests.swift @@ -35,17 +35,20 @@ final class PkgConfigParserTests: XCTestCase { func testGTK3PCFile() throws { try! loadPCFile("gtk+-3.0.pc") { parser in - XCTAssertEqual(parser.variables, [ - "libdir": "/usr/local/Cellar/gtk+3/3.18.9/lib", - "gtk_host": "x86_64-apple-darwin15.3.0", - "includedir": "/usr/local/Cellar/gtk+3/3.18.9/include", - "prefix": "/usr/local/Cellar/gtk+3/3.18.9", - "gtk_binary_version": "3.0.0", - "exec_prefix": "/usr/local/Cellar/gtk+3/3.18.9", - "targets": "quartz", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": AbsolutePath.root.pathString - ]) + XCTAssertEqual( + parser.variables, + [ + "libdir": "/usr/local/Cellar/gtk+3/3.18.9/lib", + "gtk_host": "x86_64-apple-darwin15.3.0", + "includedir": "/usr/local/Cellar/gtk+3/3.18.9/include", + "prefix": "/usr/local/Cellar/gtk+3/3.18.9", + "gtk_binary_version": "3.0.0", + "exec_prefix": "/usr/local/Cellar/gtk+3/3.18.9", + "targets": "quartz", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": AbsolutePath.root.pathString, + ] + ) XCTAssertEqual(parser.dependencies, ["gdk-3.0", "atk", "cairo", "cairo-gobject", "gdk-pixbuf-2.0", "gio-2.0"]) XCTAssertEqual(parser.privateDependencies, ["atk", "epoxy", "gio-unix-2.0"]) XCTAssertEqual(parser.cFlags, ["-I/usr/local/Cellar/gtk+3/3.18.9/include/gtk-3.0"]) @@ -55,12 +58,15 @@ final class PkgConfigParserTests: XCTestCase { func testEmptyCFlags() throws { try! loadPCFile("empty_cflags.pc") { parser in - XCTAssertEqual(parser.variables, [ - "prefix": "/usr/local/bin", - "exec_prefix": "/usr/local/bin", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": AbsolutePath.root.pathString - ]) + XCTAssertEqual( + parser.variables, + [ + "prefix": "/usr/local/bin", + "exec_prefix": "/usr/local/bin", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": AbsolutePath.root.pathString, + ] + ) XCTAssertEqual(parser.dependencies, ["gdk-3.0", "atk"]) XCTAssertEqual(parser.cFlags, []) XCTAssertEqual(parser.libs, ["-L/usr/local/bin", "-lgtk-3"]) @@ -75,13 +81,16 @@ final class PkgConfigParserTests: XCTestCase { func testVariableinDependency() throws { try! loadPCFile("deps_variable.pc") { parser in - XCTAssertEqual(parser.variables, [ - "prefix": "/usr/local/bin", - "exec_prefix": "/usr/local/bin", - "my_dep": "atk", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": AbsolutePath.root.pathString - ]) + XCTAssertEqual( + parser.variables, + [ + "prefix": "/usr/local/bin", + "exec_prefix": "/usr/local/bin", + "my_dep": "atk", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": AbsolutePath.root.pathString, + ] + ) XCTAssertEqual(parser.dependencies, ["gdk-3.0", "atk"]) XCTAssertEqual(parser.cFlags, ["-I"]) XCTAssertEqual(parser.libs, ["-L/usr/local/bin", "-lgtk-3"]) @@ -99,13 +108,16 @@ final class PkgConfigParserTests: XCTestCase { func testEscapedSpaces() throws { try! loadPCFile("escaped_spaces.pc") { parser in - XCTAssertEqual(parser.variables, [ - "prefix": "/usr/local/bin", - "exec_prefix": "/usr/local/bin", - "my_dep": "atk", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": AbsolutePath.root.pathString - ]) + XCTAssertEqual( + parser.variables, + [ + "prefix": "/usr/local/bin", + "exec_prefix": "/usr/local/bin", + "my_dep": "atk", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": AbsolutePath.root.pathString, + ] + ) XCTAssertEqual(parser.dependencies, ["gdk-3.0", "atk"]) XCTAssertEqual(parser.cFlags, ["-I/usr/local/Wine Cellar/gtk+3/3.18.9/include/gtk-3.0", "-I/after/extra/spaces"]) XCTAssertEqual(parser.libs, ["-L/usr/local/bin", "-lgtk 3", "-wantareal\\here", "-one\\", "-two"]) @@ -114,12 +126,15 @@ final class PkgConfigParserTests: XCTestCase { func testDummyDependency() throws { try loadPCFile("dummy_dependency.pc") { parser in - XCTAssertEqual(parser.variables, [ - "prefix": "/usr/local/bin", - "exec_prefix": "/usr/local/bin", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": AbsolutePath.root.pathString - ]) + XCTAssertEqual( + parser.variables, + [ + "prefix": "/usr/local/bin", + "exec_prefix": "/usr/local/bin", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": AbsolutePath.root.pathString, + ] + ) XCTAssertEqual(parser.dependencies, ["pango", "fontconfig"]) XCTAssertEqual(parser.cFlags, []) XCTAssertEqual(parser.libs, ["-L/usr/local/bin", "-lpangoft2-1.0"]) @@ -133,10 +148,12 @@ final class PkgConfigParserTests: XCTestCase { /// Temporary workaround for PCFileFinder's use of static variables. PCFileFinder.resetCachedPkgConfigPaths() - let fs = InMemoryFileSystem(emptyFiles: - "/usr/lib/pkgconfig/foo.pc", + let fs = InMemoryFileSystem( + emptyFiles: + "/usr/lib/pkgconfig/foo.pc", "/usr/local/opt/foo/lib/pkgconfig/foo.pc", - "/custom/foo.pc") + "/custom/foo.pc" + ) XCTAssertEqual( "/custom/foo.pc", try PCFileFinder().locatePCFile(name: "foo", customSearchPaths: ["/custom"], fileSystem: fs, observabilityScope: observability.topScope) @@ -152,11 +169,11 @@ final class PkgConfigParserTests: XCTestCase { try Environment.makeCustom(["PKG_CONFIG_PATH": "/usr/local/opt/foo/lib/pkgconfig"]) { XCTAssertEqual("/usr/local/opt/foo/lib/pkgconfig/foo.pc", try PkgConfig(name: "foo", fileSystem: fs, observabilityScope: observability.topScope).pcFile) } -#if os(Windows) - let separator = ";" -#else - let separator = ":" -#endif + #if os(Windows) + let separator = ";" + #else + let separator = ":" + #endif try Environment.makeCustom(["PKG_CONFIG_PATH": "/usr/local/opt/foo/lib/pkgconfig\(separator)/usr/lib/pkgconfig"]) { XCTAssertEqual("/usr/local/opt/foo/lib/pkgconfig/foo.pc", try PkgConfig(name: "foo", fileSystem: fs, observabilityScope: observability.topScope).pcFile) } @@ -167,32 +184,32 @@ final class PkgConfigParserTests: XCTestCase { PCFileFinder.resetCachedPkgConfigPaths() try testWithTemporaryDirectory { tmpdir in -#if os(Windows) - let fakePkgConfig = tmpdir.appending(components: "bin", "pkg-config.cmd") -#else - let fakePkgConfig = tmpdir.appending(components: "bin", "pkg-config") -#endif + #if os(Windows) + let fakePkgConfig = tmpdir.appending(components: "bin", "pkg-config.cmd") + #else + let fakePkgConfig = tmpdir.appending(components: "bin", "pkg-config") + #endif try localFileSystem.createDirectory(fakePkgConfig.parentDirectory) -#if os(Windows) - let script = """ - @echo off - echo /Volumes/BestDrive/pkgconfig - """ -#else - let script = """ - #!/bin/sh - echo "/Volumes/BestDrive/pkgconfig" - """ -#endif + #if os(Windows) + let script = """ + @echo off + echo /Volumes/BestDrive/pkgconfig + """ + #else + let script = """ + #!/bin/sh + echo "/Volumes/BestDrive/pkgconfig" + """ + #endif try localFileSystem.writeFileContents(fakePkgConfig, string: script) try localFileSystem.chmod(.executable, path: fakePkgConfig, options: []) -#if os(Windows) - _ = PCFileFinder(pkgConfig: fakePkgConfig) -#else - _ = PCFileFinder(brewPrefix: fakePkgConfig.parentDirectory.parentDirectory) -#endif + #if os(Windows) + _ = PCFileFinder(pkgConfig: fakePkgConfig) + #else + _ = PCFileFinder(brewPrefix: fakePkgConfig.parentDirectory.parentDirectory) + #endif } XCTAssertEqual(PCFileFinder.pkgConfigPaths, ["/Volumes/BestDrive/pkgconfig"]) @@ -214,7 +231,7 @@ final class PkgConfigParserTests: XCTestCase { let fileSystem = try InMemoryFileSystem( files: [ "/usr/local/opt/glib/lib/pkgconfig/gobject-2.0.pc": pcFileByteString("gobject-2.0.pc"), - libffiPath: pcFileByteString("libffi.pc") + libffiPath: pcFileByteString("libffi.pc"), ] ) @@ -243,17 +260,20 @@ final class PkgConfigParserTests: XCTestCase { func testSysrootDir() throws { // sysroot should be prepended to all path variables, and should therefore appear in cflags and libs. try loadPCFile("gtk+-3.0.pc", sysrootDir: "/opt/sysroot/somewhere") { parser in - XCTAssertEqual(parser.variables, [ - "libdir": "/opt/sysroot/somewhere/usr/local/Cellar/gtk+3/3.18.9/lib", - "gtk_host": "x86_64-apple-darwin15.3.0", - "includedir": "/opt/sysroot/somewhere/usr/local/Cellar/gtk+3/3.18.9/include", - "prefix": "/opt/sysroot/somewhere/usr/local/Cellar/gtk+3/3.18.9", - "gtk_binary_version": "3.0.0", - "exec_prefix": "/opt/sysroot/somewhere/usr/local/Cellar/gtk+3/3.18.9", - "targets": "quartz", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": "/opt/sysroot/somewhere" - ]) + XCTAssertEqual( + parser.variables, + [ + "libdir": "/opt/sysroot/somewhere/usr/local/Cellar/gtk+3/3.18.9/lib", + "gtk_host": "x86_64-apple-darwin15.3.0", + "includedir": "/opt/sysroot/somewhere/usr/local/Cellar/gtk+3/3.18.9/include", + "prefix": "/opt/sysroot/somewhere/usr/local/Cellar/gtk+3/3.18.9", + "gtk_binary_version": "3.0.0", + "exec_prefix": "/opt/sysroot/somewhere/usr/local/Cellar/gtk+3/3.18.9", + "targets": "quartz", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": "/opt/sysroot/somewhere", + ] + ) XCTAssertEqual(parser.dependencies, ["gdk-3.0", "atk", "cairo", "cairo-gobject", "gdk-pixbuf-2.0", "gio-2.0"]) XCTAssertEqual(parser.privateDependencies, ["atk", "epoxy", "gio-unix-2.0"]) XCTAssertEqual(parser.cFlags, ["-I/opt/sysroot/somewhere/usr/local/Cellar/gtk+3/3.18.9/include/gtk-3.0"]) @@ -266,17 +286,20 @@ final class PkgConfigParserTests: XCTestCase { // https://github.com/pkgconf/pkgconf/issues/213 // SwiftPM does not currently implement this special case. try loadPCFile("gtk+-3.0.pc", sysrootDir: "/usr/local/Cellar") { parser in - XCTAssertEqual(parser.variables, [ - "libdir": "/usr/local/Cellar/gtk+3/3.18.9/lib", - "gtk_host": "x86_64-apple-darwin15.3.0", - "includedir": "/usr/local/Cellar/gtk+3/3.18.9/include", - "prefix": "/usr/local/Cellar/gtk+3/3.18.9", - "gtk_binary_version": "3.0.0", - "exec_prefix": "/usr/local/Cellar/gtk+3/3.18.9", - "targets": "quartz", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": "/usr/local/Cellar" - ]) + XCTAssertEqual( + parser.variables, + [ + "libdir": "/usr/local/Cellar/gtk+3/3.18.9/lib", + "gtk_host": "x86_64-apple-darwin15.3.0", + "includedir": "/usr/local/Cellar/gtk+3/3.18.9/include", + "prefix": "/usr/local/Cellar/gtk+3/3.18.9", + "gtk_binary_version": "3.0.0", + "exec_prefix": "/usr/local/Cellar/gtk+3/3.18.9", + "targets": "quartz", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": "/usr/local/Cellar", + ] + ) XCTAssertEqual(parser.dependencies, ["gdk-3.0", "atk", "cairo", "cairo-gobject", "gdk-pixbuf-2.0", "gio-2.0"]) XCTAssertEqual(parser.privateDependencies, ["atk", "epoxy", "gio-unix-2.0"]) XCTAssertEqual(parser.cFlags, ["-I/usr/local/Cellar/gtk+3/3.18.9/include/gtk-3.0"]) @@ -286,37 +309,46 @@ final class PkgConfigParserTests: XCTestCase { // sysroot should be not be double-prepended if it is used explicitly by the .pc file // - pkgconf makes this check, but pkg-config does not try loadPCFile("double_sysroot.pc", sysrootDir: "/sysroot") { parser in - XCTAssertEqual(parser.variables, [ - "prefix": "/sysroot/usr", - "datarootdir": "/sysroot/usr/share", - "pkgdatadir": "/sysroot/usr/share/pkgdata", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": "/sysroot" - ]) + XCTAssertEqual( + parser.variables, + [ + "prefix": "/sysroot/usr", + "datarootdir": "/sysroot/usr/share", + "pkgdatadir": "/sysroot/usr/share/pkgdata", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": "/sysroot", + ] + ) } // pkgconfig strips a leading sysroot prefix if sysroot appears anywhere else in the // expanded variable. SwiftPM's implementation is faithful to pkgconfig, even // thought it might seem more logical not to strip the prefix in this case. try loadPCFile("not_double_sysroot.pc", sysrootDir: "/sysroot") { parser in - XCTAssertEqual(parser.variables, [ - "prefix": "/sysroot/usr", - "datarootdir": "/sysroot/usr/share", - "pkgdatadir": "/filler/sysroot/usr/share/pkgdata", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": "/sysroot" - ]) + XCTAssertEqual( + parser.variables, + [ + "prefix": "/sysroot/usr", + "datarootdir": "/sysroot/usr/share", + "pkgdatadir": "/filler/sysroot/usr/share/pkgdata", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": "/sysroot", + ] + ) } // pkgconfig does not strip sysroot if it is a relative path try loadPCFile("double_sysroot.pc", sysrootDir: "sysroot") { parser in - XCTAssertEqual(parser.variables, [ - "prefix": "sysroot/usr", - "datarootdir": "sysroot/usr/share", - "pkgdatadir": "sysroot/sysroot/usr/share/pkgdata", - "pcfiledir": parser.pcFile.parentDirectory.pathString, - "pc_sysrootdir": "sysroot" - ]) + XCTAssertEqual( + parser.variables, + [ + "prefix": "sysroot/usr", + "datarootdir": "sysroot/usr/share", + "pkgdatadir": "sysroot/sysroot/usr/share/pkgdata", + "pcfiledir": parser.pcFile.parentDirectory.pathString, + "pc_sysrootdir": "sysroot", + ] + ) } } diff --git a/Tests/PackageLoadingTests/PkgConfigTests.swift b/Tests/PackageLoadingTests/PkgConfigTests.swift index 094b485b478..919007e0e5d 100644 --- a/Tests/PackageLoadingTests/PkgConfigTests.swift +++ b/Tests/PackageLoadingTests/PkgConfigTests.swift @@ -22,7 +22,8 @@ extension SystemLibraryModule { name: "Foo", path: "/fake", pkgConfig: pkgConfig.isEmpty ? nil : pkgConfig, - providers: providers.isEmpty ? nil : providers) + providers: providers.isEmpty ? nil : providers + ) } } @@ -58,7 +59,8 @@ class PkgConfigTests: XCTestCase { for: target, pkgConfigDirectories: [], fileSystem: fs, - observabilityScope: observability.topScope) { + observabilityScope: observability.topScope + ) { XCTAssertEqual(result.pkgConfigName, "Foo") XCTAssertEqual(result.cFlags, []) XCTAssertEqual(result.libs, []) diff --git a/Tests/PackageLoadingTests/TargetSourcesBuilderTests.swift b/Tests/PackageLoadingTests/TargetSourcesBuilderTests.swift index b8ac83dabd0..c995095224c 100644 --- a/Tests/PackageLoadingTests/TargetSourcesBuilderTests.swift +++ b/Tests/PackageLoadingTests/TargetSourcesBuilderTests.swift @@ -32,18 +32,21 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/Foo.swift", - "/Bar.swift", - "/some/path.swift", - "/some2/path2.swift", - "/.some2/hello.swift", - "/Hello.something/hello.txt", - "/file", - "/path/to/file.xcodeproj/pbxproj", - "/path/to/somefile.txt", - "/some/path/toBeCopied/cool/hello.swift", - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/Foo.swift", + "/Bar.swift", + "/some/path.swift", + "/some2/path2.swift", + "/.some2/hello.swift", + "/Hello.something/hello.txt", + "/file", + "/path/to/file.xcodeproj/pbxproj", + "/path/to/somefile.txt", + "/some/path/toBeCopied/cool/hello.swift", + ] + ) let observability = ObservabilitySystem.makeForTesting() @@ -60,15 +63,18 @@ final class TargetSourcesBuilderTests: XCTestCase { let contents = builder.computeContents().sorted() - XCTAssertEqual(contents, [ - "/Bar.swift", - "/Foo.swift", - "/Hello.something/hello.txt", - "/file", - "/path/to/somefile.txt", - "/some/path.swift", - "/some/path/toBeCopied", - ]) + XCTAssertEqual( + contents, + [ + "/Bar.swift", + "/Foo.swift", + "/Hello.something/hello.txt", + "/file", + "/path/to/somefile.txt", + "/some/path.swift", + "/some/path/toBeCopied", + ] + ) XCTAssertNoDiagnostics(observability.diagnostics) } @@ -84,10 +90,13 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/some/hello.swift", - "/some.thing/hello.txt", - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/some/hello.swift", + "/some.thing/hello.txt", + ] + ) let observability = ObservabilitySystem.makeForTesting() @@ -104,10 +113,13 @@ final class TargetSourcesBuilderTests: XCTestCase { let contents = builder.computeContents().sorted() - XCTAssertEqual(contents, [ - "/some.thing", - "/some/hello.swift", - ]) + XCTAssertEqual( + contents, + [ + "/some.thing", + "/some/hello.swift", + ] + ) XCTAssertNoDiagnostics(observability.diagnostics) } @@ -123,10 +135,13 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/some/hello.swift", - "/some.thing/hello.txt", - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/some/hello.swift", + "/some.thing/hello.txt", + ] + ) let observability = ObservabilitySystem.makeForTesting() @@ -143,10 +158,13 @@ final class TargetSourcesBuilderTests: XCTestCase { let contents = builder.computeContents().sorted() - XCTAssertEqual(contents, [ - "/some.thing/hello.txt", - "/some/hello.swift", - ]) + XCTAssertEqual( + contents, + [ + "/some.thing/hello.txt", + "/some/hello.swift", + ] + ) XCTAssertNoDiagnostics(observability.diagnostics) } @@ -164,10 +182,13 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - root.appending(components: "some.xcassets", "hello.txt").pathString, - root.appending(components: "some", "hello.swift").pathString - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + root.appending(components: "some.xcassets", "hello.txt").pathString, + root.appending(components: "some", "hello.swift").pathString, + ] + ) let observability = ObservabilitySystem.makeForTesting() @@ -184,10 +205,13 @@ final class TargetSourcesBuilderTests: XCTestCase { let contents = builder.computeContents().sorted() - XCTAssertEqual(contents, [ - root.appending(components: "some.xcassets"), - root.appending(components: "some", "hello.swift"), - ]) + XCTAssertEqual( + contents, + [ + root.appending(components: "some.xcassets"), + root.appending(components: "some", "hello.swift"), + ] + ) XCTAssertNoDiagnostics(observability.diagnostics) } @@ -207,24 +231,28 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/Foo.swift", - "/Bar.swift", - "/some/path.swift", - "/some2/path2.swift", - "/.some2/hello.swift", - "/Hello.something/hello.txt", - "/file", - "/path/to/file.xcodeproj/pbxproj", - "/path/to/somefile.txt", - "/path/to/somefile2.txt", - "/some/path/toBeCopied/cool/hello.swift", - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/Foo.swift", + "/Bar.swift", + "/some/path.swift", + "/some2/path2.swift", + "/.some2/hello.swift", + "/Hello.something/hello.txt", + "/file", + "/path/to/file.xcodeproj/pbxproj", + "/path/to/somefile.txt", + "/path/to/somefile2.txt", + "/some/path/toBeCopied/cool/hello.swift", + ] + ) let somethingRule = FileRuleDescription( rule: .processResource(localization: .none), toolsVersion: .minimumRequired, - fileTypes: ["something"]) + fileTypes: ["something"] + ) build(target: target, additionalFileRules: [somethingRule], toolsVersion: .v5, fs: fs) { _, _, _, _, _, _, _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -270,12 +298,16 @@ final class TargetSourcesBuilderTests: XCTestCase { // Conflict between processed resources. do { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "Resources") - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "Resources") + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/Resources/foo.txt", + let fs = InMemoryFileSystem( + emptyFiles: + "/Resources/foo.txt", "/Resources/Sub/foo.txt" ) @@ -298,13 +330,17 @@ final class TargetSourcesBuilderTests: XCTestCase { // Conflict between processed and copied resources. do { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "Processed"), - .init(rule: .copy, path: "Copied/foo.txt"), - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "Processed"), + .init(rule: .copy, path: "Copied/foo.txt"), + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/Processed/foo.txt", + let fs = InMemoryFileSystem( + emptyFiles: + "/Processed/foo.txt", "/Copied/foo.txt" ) @@ -327,13 +363,17 @@ final class TargetSourcesBuilderTests: XCTestCase { // No conflict between processed and copied in sub-path resources. do { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "Processed"), - .init(rule: .copy, path: "Copied"), - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "Processed"), + .init(rule: .copy, path: "Copied"), + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/Processed/foo.txt", + let fs = InMemoryFileSystem( + emptyFiles: + "/Processed/foo.txt", "/Copied/foo.txt" ) @@ -345,13 +385,17 @@ final class TargetSourcesBuilderTests: XCTestCase { // Conflict between copied directory resources. do { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .copy, path: "A/Copy"), - .init(rule: .copy, path: "B/Copy"), - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .copy, path: "A/Copy"), + .init(rule: .copy, path: "B/Copy"), + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/A/Copy/foo.txt", + let fs = InMemoryFileSystem( + emptyFiles: + "/A/Copy/foo.txt", "/B/Copy/foo.txt" ) @@ -374,13 +418,17 @@ final class TargetSourcesBuilderTests: XCTestCase { // Conflict between processed localizations. do { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "A"), - .init(rule: .process(localization: .none), path: "B"), - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "A"), + .init(rule: .process(localization: .none), path: "B"), + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/A/en.lproj/foo.txt", + let fs = InMemoryFileSystem( + emptyFiles: + "/A/en.lproj/foo.txt", "/B/EN.lproj/foo.txt" ) @@ -403,13 +451,17 @@ final class TargetSourcesBuilderTests: XCTestCase { // Conflict between processed localizations and copied resources. do { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "A"), - .init(rule: .copy, path: "B/en.lproj"), - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "A"), + .init(rule: .copy, path: "B/en.lproj"), + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/A/EN.lproj/foo.txt", + let fs = InMemoryFileSystem( + emptyFiles: + "/A/EN.lproj/foo.txt", "/B/en.lproj/foo.txt" ) @@ -430,8 +482,9 @@ final class TargetSourcesBuilderTests: XCTestCase { func testLocalizationDirectoryIgnoredOn5_2() throws { let target = try TargetDescription(name: "Foo") - let fs = InMemoryFileSystem(emptyFiles: - "/en.lproj/Localizable.strings" + let fs = InMemoryFileSystem( + emptyFiles: + "/en.lproj/Localizable.strings" ) build(target: target, toolsVersion: .v5_2, fs: fs) { _, resources, _, _, _, _, _, diagnostics in @@ -441,13 +494,17 @@ final class TargetSourcesBuilderTests: XCTestCase { } func testLocalizationDirectorySubDirectory() throws { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "Processed"), - .init(rule: .copy, path: "Copied") - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "Processed"), + .init(rule: .copy, path: "Copied"), + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/Processed/en.lproj/sub/Localizable.strings", + let fs = InMemoryFileSystem( + emptyFiles: + "/Processed/en.lproj/sub/Localizable.strings", "/Copied/en.lproj/sub/Localizable.strings" ) @@ -465,21 +522,27 @@ final class TargetSourcesBuilderTests: XCTestCase { } func testExplicitLocalizationInLocalizationDirectory() throws { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .base), path: "Resources"), - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .base), path: "Resources") + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/Resources/en.lproj/Localizable.strings" + let fs = InMemoryFileSystem( + emptyFiles: + "/Resources/en.lproj/Localizable.strings" ) build(target: target, toolsVersion: .v5_3, fs: fs) { _, _, _, _, identity, kind, path, diagnostics in testDiagnostics(diagnostics) { result in let diagnostic = result.check( - diagnostic: .contains(""" + diagnostic: .contains( + """ resource '\(RelativePath("Resources").appending(components: "en.lproj", "Localizable.strings"))' in target 'Foo' is in a localization directory \ and has an explicit localization declaration - """), + """ + ), severity: .error ) XCTAssertEqual(diagnostic?.metadata?.packageIdentity, identity) @@ -492,14 +555,18 @@ final class TargetSourcesBuilderTests: XCTestCase { // rdar://86297221 // There is no need to validate localization exists for default localization func testMissingDefaultLocalization() throws { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "Resources"), - .init(rule: .process(localization: .default), path: "Image.png"), - .init(rule: .process(localization: .base), path: "Icon.png"), - ]) - - let fs = InMemoryFileSystem(emptyFiles: - "/Resources/en.lproj/Localizable.strings", + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "Resources"), + .init(rule: .process(localization: .default), path: "Image.png"), + .init(rule: .process(localization: .base), path: "Icon.png"), + ] + ) + + let fs = InMemoryFileSystem( + emptyFiles: + "/Resources/en.lproj/Localizable.strings", "/Resources/en.lproj/Icon.png", "/Resources/fr.lproj/Localizable.strings", "/Resources/fr.lproj/Sign.png", @@ -522,14 +589,18 @@ final class TargetSourcesBuilderTests: XCTestCase { } func testLocalizedAndUnlocalizedResources() throws { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "Resources"), - .init(rule: .process(localization: .default), path: "Image.png"), - .init(rule: .process(localization: .base), path: "Icon.png"), - ]) - - let fs = InMemoryFileSystem(emptyFiles: - "/Resources/en.lproj/Localizable.strings", + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "Resources"), + .init(rule: .process(localization: .default), path: "Image.png"), + .init(rule: .process(localization: .base), path: "Icon.png"), + ] + ) + + let fs = InMemoryFileSystem( + emptyFiles: + "/Resources/en.lproj/Localizable.strings", "/Resources/Localizable.strings", "/Resources/Base.lproj/Storyboard.storyboard", "/Resources/Storyboard.storyboard", @@ -542,22 +613,30 @@ final class TargetSourcesBuilderTests: XCTestCase { build(target: target, toolsVersion: .v5_3, fs: fs) { _, _, _, _, identity, kind, path, diagnostics in testDiagnostics(diagnostics) { result in var diagnosticsFound = [Basics.Diagnostic?]() - diagnosticsFound.append(result.checkUnordered( - diagnostic: .contains("resource 'Localizable.strings' in target 'Foo' has both localized and un-localized variants"), - severity: .warning - )) - diagnosticsFound.append(result.checkUnordered( - diagnostic: .contains("resource 'Storyboard.storyboard' in target 'Foo' has both localized and un-localized variants"), - severity: .warning - )) - diagnosticsFound.append(result.checkUnordered( - diagnostic: .contains("resource 'Image.png' in target 'Foo' has both localized and un-localized variants"), - severity: .warning - )) - diagnosticsFound.append(result.checkUnordered( - diagnostic: .contains("resource 'Icon.png' in target 'Foo' has both localized and un-localized variants"), - severity: .warning - )) + diagnosticsFound.append( + result.checkUnordered( + diagnostic: .contains("resource 'Localizable.strings' in target 'Foo' has both localized and un-localized variants"), + severity: .warning + ) + ) + diagnosticsFound.append( + result.checkUnordered( + diagnostic: .contains("resource 'Storyboard.storyboard' in target 'Foo' has both localized and un-localized variants"), + severity: .warning + ) + ) + diagnosticsFound.append( + result.checkUnordered( + diagnostic: .contains("resource 'Image.png' in target 'Foo' has both localized and un-localized variants"), + severity: .warning + ) + ) + diagnosticsFound.append( + result.checkUnordered( + diagnostic: .contains("resource 'Icon.png' in target 'Foo' has both localized and un-localized variants"), + severity: .warning + ) + ) for diagnostic in diagnosticsFound { XCTAssertEqual(diagnostic?.metadata?.packageIdentity, identity) @@ -569,15 +648,19 @@ final class TargetSourcesBuilderTests: XCTestCase { } func testLocalizedResources() throws { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "Processed"), - .init(rule: .copy, path: "Copied"), - .init(rule: .process(localization: .base), path: "Other/Launch.storyboard"), - .init(rule: .process(localization: .default), path: "Other/Image.png"), - ]) - - let fs = InMemoryFileSystem(emptyFiles: - "/Processed/foo.txt", + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "Processed"), + .init(rule: .copy, path: "Copied"), + .init(rule: .process(localization: .base), path: "Other/Launch.storyboard"), + .init(rule: .process(localization: .default), path: "Other/Image.png"), + ] + ) + + let fs = InMemoryFileSystem( + emptyFiles: + "/Processed/foo.txt", "/Processed/En-uS.lproj/Localizable.stringsdict", "/Processed/en-US.lproj/Localizable.strings", "/Processed/fr.lproj/Localizable.strings", @@ -588,43 +671,54 @@ final class TargetSourcesBuilderTests: XCTestCase { "/Other/Image.png" ) - build(target: target, defaultLocalization: "fr", toolsVersion: .v5_3, fs: fs) { _, resources, _, _, _, _, _, diagnostics in - XCTAssertEqual(resources.sorted(by: { $0.path < $1.path }), [ - Resource(rule: .process(localization: .none), path: "/Processed/foo.txt"), - Resource(rule: .process(localization: "en-us"), path: "/Processed/En-uS.lproj/Localizable.stringsdict"), - Resource(rule: .process(localization: "en-us"), path: "/Processed/en-US.lproj/Localizable.strings"), - Resource(rule: .process(localization: "fr"), path: "/Processed/fr.lproj/Localizable.strings"), - Resource(rule: .process(localization: "fr"), path: "/Processed/fr.lproj/Localizable.stringsdict"), - Resource(rule: .process(localization: "Base"), path: "/Processed/Base.lproj/Storyboard.storyboard"), - Resource(rule: .copy, path: "/Copied"), - Resource(rule: .process(localization: "Base"), path: "/Other/Launch.storyboard"), - Resource(rule: .process(localization: "fr"), path: "/Other/Image.png"), - ].sorted(by: { $0.path < $1.path })) + build(target: target, defaultLocalization: "fr", toolsVersion: .v5_3, fs: fs) { _, resources, _, _, _, _, _, diagnostics in + XCTAssertEqual( + resources.sorted(by: { $0.path < $1.path }), + [ + Resource(rule: .process(localization: .none), path: "/Processed/foo.txt"), + Resource(rule: .process(localization: "en-us"), path: "/Processed/En-uS.lproj/Localizable.stringsdict"), + Resource(rule: .process(localization: "en-us"), path: "/Processed/en-US.lproj/Localizable.strings"), + Resource(rule: .process(localization: "fr"), path: "/Processed/fr.lproj/Localizable.strings"), + Resource(rule: .process(localization: "fr"), path: "/Processed/fr.lproj/Localizable.stringsdict"), + Resource(rule: .process(localization: "Base"), path: "/Processed/Base.lproj/Storyboard.storyboard"), + Resource(rule: .copy, path: "/Copied"), + Resource(rule: .process(localization: "Base"), path: "/Other/Launch.storyboard"), + Resource(rule: .process(localization: "fr"), path: "/Other/Image.png"), + ].sorted(by: { $0.path < $1.path }) + ) } } func testLocalizedImage() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Foo/fr.lproj/Image.png", + let fs = InMemoryFileSystem( + emptyFiles: + "/Foo/fr.lproj/Image.png", "/Foo/es.lproj/Image.png" ) build(target: try TargetDescription(name: "Foo"), defaultLocalization: "fr", toolsVersion: .v5_3, fs: fs) { _, resources, _, _, _, _, _, diagnostics in - XCTAssertEqual(resources.sorted(by: { $0.path < $1.path }), [ - Resource(rule: .process(localization: "fr"), path: "/Foo/fr.lproj/Image.png"), - Resource(rule: .process(localization: "es"), path: "/Foo/es.lproj/Image.png"), - ].sorted(by: { $0.path < $1.path })) + XCTAssertEqual( + resources.sorted(by: { $0.path < $1.path }), + [ + Resource(rule: .process(localization: "fr"), path: "/Foo/fr.lproj/Image.png"), + Resource(rule: .process(localization: "es"), path: "/Foo/es.lproj/Image.png"), + ].sorted(by: { $0.path < $1.path }) + ) } } func testInfoPlistResource() throws { do { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .process(localization: .none), path: "Resources"), - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .process(localization: .none), path: "Resources") + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/Resources/Processed/Info.plist" + let fs = InMemoryFileSystem( + emptyFiles: + "/Resources/Processed/Info.plist" ) build(target: target, toolsVersion: .v5_3, fs: fs) { _, _, _, _, identity, kind, path, diagnostics in @@ -641,12 +735,16 @@ final class TargetSourcesBuilderTests: XCTestCase { } do { - let target = try TargetDescription(name: "Foo", resources: [ - .init(rule: .copy, path: "Resources/Copied/Info.plist"), - ]) + let target = try TargetDescription( + name: "Foo", + resources: [ + .init(rule: .copy, path: "Resources/Copied/Info.plist") + ] + ) - let fs = InMemoryFileSystem(emptyFiles: - "/Resources/Copied/Info.plist" + let fs = InMemoryFileSystem( + emptyFiles: + "/Resources/Copied/Info.plist" ) build(target: target, toolsVersion: .v5_3, fs: fs) { _, _, _, _, identity, kind, path, diagnostics in @@ -675,11 +773,13 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/Foo.swift", - "/Bar.swift" - ]) - + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/Foo.swift", + "/Bar.swift", + ] + ) do { let observability = ObservabilitySystem.makeForTesting() @@ -729,24 +829,29 @@ final class TargetSourcesBuilderTests: XCTestCase { XCTAssertNoDiagnostics(observability.diagnostics) } } - + func testMissingResource() throws { let target = try TargetDescription( name: "Foo", path: nil, exclude: [], sources: nil, - resources: [.init(rule: .copy, path: "../../../Fake.txt"), - .init(rule: .process(localization: .none), path: "NotReal")], + resources: [ + .init(rule: .copy, path: "../../../Fake.txt"), + .init(rule: .process(localization: .none), path: "NotReal"), + ], publicHeadersPath: nil, type: .regular ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/Foo.swift", - "/Bar.swift" - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/Foo.swift", + "/Bar.swift", + ] + ) do { let observability = ObservabilitySystem.makeForTesting() @@ -797,25 +902,29 @@ final class TargetSourcesBuilderTests: XCTestCase { } } - func testMissingSource() throws { let target = try TargetDescription( name: "Foo", path: nil, exclude: [], - sources: ["InvalidPackage.swift", - "DoesNotExist.swift", - "../../Tests/InvalidPackageTests/InvalidPackageTests.swift"], + sources: [ + "InvalidPackage.swift", + "DoesNotExist.swift", + "../../Tests/InvalidPackageTests/InvalidPackageTests.swift", + ], resources: [], publicHeadersPath: nil, type: .regular ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/Foo.swift", - "/Bar.swift" - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/Foo.swift", + "/Bar.swift", + ] + ) let observability = ObservabilitySystem.makeForTesting() @@ -856,16 +965,19 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/File.swift", - "/Foo.xcdatamodel" - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/File.swift", + "/Foo.xcdatamodel", + ] + ) let observability = ObservabilitySystem.makeForTesting() let builder = TargetSourcesBuilder( packageIdentity: .plain("test"), - packageKind: .root( "/test"), + packageKind: .root("/test"), packagePath: .root, target: target, path: .root, @@ -895,10 +1007,13 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/File.swift", - "/foo.bar" - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/File.swift", + "/foo.bar", + ] + ) do { let observability = ObservabilitySystem.makeForTesting() @@ -956,10 +1071,13 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/File.swift", - "/Foo.docc" - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/File.swift", + "/Foo.docc", + ] + ) let observability = ObservabilitySystem.makeForTesting() @@ -1000,12 +1118,15 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let fs = InMemoryFileSystem() - fs.createEmptyFiles(at: AbsolutePath.root, files: [ - "/File.swift", - "/a.txt", - "/b.txt", - "/c.txt", - ]) + fs.createEmptyFiles( + at: AbsolutePath.root, + files: [ + "/File.swift", + "/a.txt", + "/b.txt", + "/c.txt", + ] + ) let observability = ObservabilitySystem.makeForTesting() @@ -1023,11 +1144,14 @@ final class TargetSourcesBuilderTests: XCTestCase { ) let outputs = try builder.run() XCTAssertEqual(outputs.sources.paths, ["/File.swift"]) - XCTAssertEqual(outputs.resources, [ - .init(rule: .copy, path: try .init(validating: "/a.txt")), - .init(rule: .copy, path: try .init(validating: "/b.txt")), - .init(rule: .copy, path: try .init(validating: "/c.txt")), - ]) + XCTAssertEqual( + outputs.resources, + [ + .init(rule: .copy, path: try .init(validating: "/a.txt")), + .init(rule: .copy, path: try .init(validating: "/b.txt")), + .init(rule: .copy, path: try .init(validating: "/c.txt")), + ] + ) XCTAssertEqual(outputs.ignored, []) XCTAssertEqual(outputs.others, []) diff --git a/Tests/PackageLoadingTests/ToolsVersionParserTests.swift b/Tests/PackageLoadingTests/ToolsVersionParserTests.swift index c7c6b05778d..19d39a13075 100644 --- a/Tests/PackageLoadingTests/ToolsVersionParserTests.swift +++ b/Tests/PackageLoadingTests/ToolsVersionParserTests.swift @@ -26,82 +26,82 @@ final class ToolsVersionParserTests: XCTestCase { func testValidVersions() throws { let manifestsSnippetWithValidVersionSpecification = [ // No spacing surrounding the label for Swift ≥ 5.4: - "//swift-tools-version:5.4.0" : (5, 4, 0, "5.4.0"), - "//swift-tools-version:5.4-dev" : (5, 4, 0, "5.4.0"), - "//swift-tools-version:5.8.0" : (5, 8, 0, "5.8.0"), - "//swift-tools-version:5.8.0-dev.al+sha.x" : (5, 8, 0, "5.8.0"), - "//swift-tools-version:6.1.2" : (6, 1, 2, "6.1.2"), - "//swift-tools-version:6.1.2;" : (6, 1, 2, "6.1.2"), - "//swift-tools-vErsion:6.1.2;;;;;" : (6, 1, 2, "6.1.2"), - "//swift-tools-version:6.1.2;x;x;x;x;x;" : (6, 1, 2, "6.1.2"), - "//swift-toolS-version:5.5.2;hello" : (5, 5, 2, "5.5.2"), - "//sWiFt-tOoLs-vErSiOn:5.5.2\nkkk\n" : (5, 5, 2, "5.5.2"), + "//swift-tools-version:5.4.0": (5, 4, 0, "5.4.0"), + "//swift-tools-version:5.4-dev": (5, 4, 0, "5.4.0"), + "//swift-tools-version:5.8.0": (5, 8, 0, "5.8.0"), + "//swift-tools-version:5.8.0-dev.al+sha.x": (5, 8, 0, "5.8.0"), + "//swift-tools-version:6.1.2": (6, 1, 2, "6.1.2"), + "//swift-tools-version:6.1.2;": (6, 1, 2, "6.1.2"), + "//swift-tools-vErsion:6.1.2;;;;;": (6, 1, 2, "6.1.2"), + "//swift-tools-version:6.1.2;x;x;x;x;x;": (6, 1, 2, "6.1.2"), + "//swift-toolS-version:5.5.2;hello": (5, 5, 2, "5.5.2"), + "//sWiFt-tOoLs-vErSiOn:5.5.2\nkkk\n": (5, 5, 2, "5.5.2"), // No spacing before, and 1 space (U+0020) after the label for Swift ≥ 5.4: - "//swift-tools-version: 5.4.0" : (5, 4, 0, "5.4.0"), - "//swift-tools-version: 5.4-dev" : (5, 4, 0, "5.4.0"), - "//swift-tools-version: 5.8.0" : (5, 8, 0, "5.8.0"), - "//swift-tools-version: 5.8.0-dev.al+sha.x" : (5, 8, 0, "5.8.0"), - "//swift-tools-version: 6.1.2" : (6, 1, 2, "6.1.2"), - "//swift-tools-version: 6.1.2;" : (6, 1, 2, "6.1.2"), - "//swift-tools-vErsion: 6.1.2;;;;;" : (6, 1, 2, "6.1.2"), - "//swift-tools-version: 6.1.2;x;x;x;x;x;" : (6, 1, 2, "6.1.2"), - "//swift-toolS-version: 5.5.2;hello" : (5, 5, 2, "5.5.2"), - "//sWiFt-tOoLs-vErSiOn: 5.5.2\nkkk\n" : (5, 5, 2, "5.5.2"), + "//swift-tools-version: 5.4.0": (5, 4, 0, "5.4.0"), + "//swift-tools-version: 5.4-dev": (5, 4, 0, "5.4.0"), + "//swift-tools-version: 5.8.0": (5, 8, 0, "5.8.0"), + "//swift-tools-version: 5.8.0-dev.al+sha.x": (5, 8, 0, "5.8.0"), + "//swift-tools-version: 6.1.2": (6, 1, 2, "6.1.2"), + "//swift-tools-version: 6.1.2;": (6, 1, 2, "6.1.2"), + "//swift-tools-vErsion: 6.1.2;;;;;": (6, 1, 2, "6.1.2"), + "//swift-tools-version: 6.1.2;x;x;x;x;x;": (6, 1, 2, "6.1.2"), + "//swift-toolS-version: 5.5.2;hello": (5, 5, 2, "5.5.2"), + "//sWiFt-tOoLs-vErSiOn: 5.5.2\nkkk\n": (5, 5, 2, "5.5.2"), // 1 space (U+0020) before, and no spacing after the label: - "// swift-tools-version:3.1" : (3, 1, 0, "3.1.0"), - "// swift-tools-version:3.1-dev" : (3, 1, 0, "3.1.0"), - "// swift-tools-version:5.8.0" : (5, 8, 0, "5.8.0"), - "// swift-tools-version:5.8.0-dev.al+sha.x" : (5, 8, 0, "5.8.0"), - "// swift-tools-version:3.1.2" : (3, 1, 2, "3.1.2"), - "// swift-tools-version:3.1.2;" : (3, 1, 2, "3.1.2"), - "// swift-tools-vErsion:3.1.2;;;;;" : (3, 1, 2, "3.1.2"), - "// swift-tools-version:3.1.2;x;x;x;x;x;" : (3, 1, 2, "3.1.2"), - "// swift-toolS-version:3.5.2;hello" : (3, 5, 2, "3.5.2"), - "// sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n" : (3, 5, 2, "3.5.2"), + "// swift-tools-version:3.1": (3, 1, 0, "3.1.0"), + "// swift-tools-version:3.1-dev": (3, 1, 0, "3.1.0"), + "// swift-tools-version:5.8.0": (5, 8, 0, "5.8.0"), + "// swift-tools-version:5.8.0-dev.al+sha.x": (5, 8, 0, "5.8.0"), + "// swift-tools-version:3.1.2": (3, 1, 2, "3.1.2"), + "// swift-tools-version:3.1.2;": (3, 1, 2, "3.1.2"), + "// swift-tools-vErsion:3.1.2;;;;;": (3, 1, 2, "3.1.2"), + "// swift-tools-version:3.1.2;x;x;x;x;x;": (3, 1, 2, "3.1.2"), + "// swift-toolS-version:3.5.2;hello": (3, 5, 2, "3.5.2"), + "// sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n": (3, 5, 2, "3.5.2"), // leading line feeds (U+000A) before the specification, and 1 space (U+0020) before and no space after the label for Swift ≥ 5.4: - "\n// swift-tools-version:6.1" : (6, 1, 0, "6.1.0"), - "\n\n// swift-tools-version:6.2-dev" : (6, 2, 0, "6.2.0"), - "\n\n\n// swift-tools-version:5.8.0" : (5, 8, 0, "5.8.0"), - "\n\n\n\n// swift-tools-version:6.8.0-dev.al+sha.x" : (6, 8, 0, "6.8.0"), - "\n\n\n\n\n// swift-tools-version:7.1.2" : (7, 1, 2, "7.1.2"), - "\n\n\n\n\n\n// swift-tools-version:8.1.2;" : (8, 1, 2, "8.1.2"), - "\n\n\n\n\n\n\n// swift-tools-vErsion:9.1.2;;;;;" : (9, 1, 2, "9.1.2"), - "\n\n\n\n\n\n\n\n// swift-tools-version:6.1.2;x;x;x;x;x;" : (6, 1, 2, "6.1.2"), - "\n\n\n\n\n\n\n\n\n// swift-toolS-version:5.5.2;hello" : (5, 5, 2, "5.5.2"), - "\n\n\n\n\n\n\n\n\n\n// sWiFt-tOoLs-vErSiOn:6.5.2\nkkk\n" : (6, 5, 2, "6.5.2"), + "\n// swift-tools-version:6.1": (6, 1, 0, "6.1.0"), + "\n\n// swift-tools-version:6.2-dev": (6, 2, 0, "6.2.0"), + "\n\n\n// swift-tools-version:5.8.0": (5, 8, 0, "5.8.0"), + "\n\n\n\n// swift-tools-version:6.8.0-dev.al+sha.x": (6, 8, 0, "6.8.0"), + "\n\n\n\n\n// swift-tools-version:7.1.2": (7, 1, 2, "7.1.2"), + "\n\n\n\n\n\n// swift-tools-version:8.1.2;": (8, 1, 2, "8.1.2"), + "\n\n\n\n\n\n\n// swift-tools-vErsion:9.1.2;;;;;": (9, 1, 2, "9.1.2"), + "\n\n\n\n\n\n\n\n// swift-tools-version:6.1.2;x;x;x;x;x;": (6, 1, 2, "6.1.2"), + "\n\n\n\n\n\n\n\n\n// swift-toolS-version:5.5.2;hello": (5, 5, 2, "5.5.2"), + "\n\n\n\n\n\n\n\n\n\n// sWiFt-tOoLs-vErSiOn:6.5.2\nkkk\n": (6, 5, 2, "6.5.2"), // An assortment of horizontal whitespace characters surrounding the label for Swift ≥ 5.4: - "//swift-tools-version:\u{2002}\u{202F}\u{3000}\u{A0}\u{1680}\t\u{2000}\u{2001}5.4.0" : (5, 4, 0, "5.4.0"), - "//\u{2001}swift-tools-version:\u{2002}\u{202F}\u{3000}\u{A0}\u{1680}\t\u{2000}5.4-dev" : (5, 4, 0, "5.4.0"), - "//\t\u{2000}\u{2001}swift-tools-version:\u{2002}\u{202F}\u{3000}\u{A0}\u{1680}5.8.0" : (5, 8, 0, "5.8.0"), - "//\u{1680}\t\u{2000}\u{2001}swift-tools-version:\u{2002}\u{202F}\u{3000}\u{A0}5.8.0-dev.al+sha.x" : (5, 8, 0, "5.8.0"), - "//\u{A0}\u{1680}\t\u{2000}\u{2001}swift-tools-version:\u{2002}\u{202F}\u{3000}6.1.2" : (6, 1, 2, "6.1.2"), - "//\u{3000}\u{A0}\u{1680}\t\u{2000}\u{2001}swift-tools-version:\u{2002}\u{202F}6.1.2;" : (6, 1, 2, "6.1.2"), - "//\u{202F}\u{3000}\u{A0}\u{1680}\t\u{2000}\u{2001}swift-tools-vErsion:\u{2002}6.1.2;;;;;" : (6, 1, 2, "6.1.2"), - "//\u{2002}\u{202F}\u{3000}\u{A0}\u{1680}\t\u{2000}\u{2001}swift-tools-version:6.1.2;x;x;x;x;x;" : (6, 1, 2, "6.1.2"), - "//\u{2000}\u{2002}\u{202F}\u{3000}\t\u{2001}swift-toolS-version:\u{A0}\u{1680}5.5.2;hello" : (5, 5, 2, "5.5.2"), - "//\u{2000}\u{2001}\u{2002}\u{202F}\u{3000}\tsWiFt-tOoLs-vErSiOn:\u{A0}\u{1680}5.5.2\nkkk\n" : (5, 5, 2, "5.5.2"), + "//swift-tools-version:\u{2002}\u{202F}\u{3000}\u{A0}\u{1680}\t\u{2000}\u{2001}5.4.0": (5, 4, 0, "5.4.0"), + "//\u{2001}swift-tools-version:\u{2002}\u{202F}\u{3000}\u{A0}\u{1680}\t\u{2000}5.4-dev": (5, 4, 0, "5.4.0"), + "//\t\u{2000}\u{2001}swift-tools-version:\u{2002}\u{202F}\u{3000}\u{A0}\u{1680}5.8.0": (5, 8, 0, "5.8.0"), + "//\u{1680}\t\u{2000}\u{2001}swift-tools-version:\u{2002}\u{202F}\u{3000}\u{A0}5.8.0-dev.al+sha.x": (5, 8, 0, "5.8.0"), + "//\u{A0}\u{1680}\t\u{2000}\u{2001}swift-tools-version:\u{2002}\u{202F}\u{3000}6.1.2": (6, 1, 2, "6.1.2"), + "//\u{3000}\u{A0}\u{1680}\t\u{2000}\u{2001}swift-tools-version:\u{2002}\u{202F}6.1.2;": (6, 1, 2, "6.1.2"), + "//\u{202F}\u{3000}\u{A0}\u{1680}\t\u{2000}\u{2001}swift-tools-vErsion:\u{2002}6.1.2;;;;;": (6, 1, 2, "6.1.2"), + "//\u{2002}\u{202F}\u{3000}\u{A0}\u{1680}\t\u{2000}\u{2001}swift-tools-version:6.1.2;x;x;x;x;x;": (6, 1, 2, "6.1.2"), + "//\u{2000}\u{2002}\u{202F}\u{3000}\t\u{2001}swift-toolS-version:\u{A0}\u{1680}5.5.2;hello": (5, 5, 2, "5.5.2"), + "//\u{2000}\u{2001}\u{2002}\u{202F}\u{3000}\tsWiFt-tOoLs-vErSiOn:\u{A0}\u{1680}5.5.2\nkkk\n": (5, 5, 2, "5.5.2"), // Some leading whitespace characters, and no spacing surrounding the label for Swift ≥ 5.4: - "\u{A} //swift-tools-version:5.4.0" : (5, 4, 0, "5.4.0"), - "\u{B}\t\u{A}//swift-tools-version:5.4-dev" : (5, 4, 0, "5.4.0"), - "\u{3000}\u{A0}\u{C}//swift-tools-version:5.8.0" : (5, 8, 0, "5.8.0"), - "\u{2002}\u{D}\u{2001}//swift-tools-version:5.8.0-dev.al+sha.x" : (5, 8, 0, "5.8.0"), - "\u{D}\u{A}\u{A0}\u{1680}//swift-tools-version:6.1.2" : (6, 1, 2, "6.1.2"), - " \u{85}//swift-tools-version:6.1.2;" : (6, 1, 2, "6.1.2"), - "\u{2028}//swift-tools-vErsion:6.1.2;;;;;" : (6, 1, 2, "6.1.2"), - "\u{202F}\u{2029}//swift-tools-version:6.1.2;x;x;x;x;x;" : (6, 1, 2, "6.1.2"), - "\u{A}\u{B}\u{C}\u{D}\u{A}\u{D}\u{85}\u{202F}\u{2029}\u{2001}\u{2002}\u{205F}\u{85}\u{2028}//swift-toolS-version:5.5.2;hello" : (5, 5, 2, "5.5.2"), - "\u{B} \u{200A}\u{D}\u{A}\t\u{85}\u{85}\u{A}\u{2028}\u{2009}\u{2001}\u{C}//sWiFt-tOoLs-vErSiOn:5.5.2\nkkk\n" : (5, 5, 2, "5.5.2"), + "\u{A} //swift-tools-version:5.4.0": (5, 4, 0, "5.4.0"), + "\u{B}\t\u{A}//swift-tools-version:5.4-dev": (5, 4, 0, "5.4.0"), + "\u{3000}\u{A0}\u{C}//swift-tools-version:5.8.0": (5, 8, 0, "5.8.0"), + "\u{2002}\u{D}\u{2001}//swift-tools-version:5.8.0-dev.al+sha.x": (5, 8, 0, "5.8.0"), + "\u{D}\u{A}\u{A0}\u{1680}//swift-tools-version:6.1.2": (6, 1, 2, "6.1.2"), + " \u{85}//swift-tools-version:6.1.2;": (6, 1, 2, "6.1.2"), + "\u{2028}//swift-tools-vErsion:6.1.2;;;;;": (6, 1, 2, "6.1.2"), + "\u{202F}\u{2029}//swift-tools-version:6.1.2;x;x;x;x;x;": (6, 1, 2, "6.1.2"), + "\u{A}\u{B}\u{C}\u{D}\u{A}\u{D}\u{85}\u{202F}\u{2029}\u{2001}\u{2002}\u{205F}\u{85}\u{2028}//swift-toolS-version:5.5.2;hello": (5, 5, 2, "5.5.2"), + "\u{B} \u{200A}\u{D}\u{A}\t\u{85}\u{85}\u{A}\u{2028}\u{2009}\u{2001}\u{C}//sWiFt-tOoLs-vErSiOn:5.5.2\nkkk\n": (5, 5, 2, "5.5.2"), // Some leading whitespace characters, and an assortment of horizontal whitespace characters surrounding the label for Swift ≥ 5.4: - "\u{2002}\u{202F}\u{A}//\u{A0}\u{1680}\t\u{2004}\u{2001} \u{2002}swift-tools-version:\u{3000}5.4.0" : (5, 4, 0, "5.4.0"), - "\u{B}//\u{A0}\u{1680}\t\u{2000}\u{2001} \u{2002}swift-tools-version:\u{202F}\u{3000}5.4-dev" : (5, 4, 0, "5.4.0"), - "\u{C}//\u{A0}\u{1680}\t\u{2000}\u{2001} swift-tools-version:\u{2002}\u{202F}\u{3000}5.8.0" : (5, 8, 0, "5.8.0"), - "\u{D}//\u{A0}\u{1680}\t\u{2005} \u{202F}\u{3000}swift-tools-version:\u{2001}5.8.0-dev.al+sha.x" : (5, 8, 0, "5.8.0"), - "\u{D}\u{A}//\u{A0}\u{2001} \u{2002}\u{202F}\u{3000}swift-tools-version:\u{1680}\t\u{2000}6.1.2" : (6, 1, 2, "6.1.2"), - "\u{85}//\u{2000}\u{2001} \u{2006}\u{202F}\u{3000}swift-tools-version:\u{A0}\u{1680}\t6.1.2;" : (6, 1, 2, "6.1.2"), - "\u{2028}//\u{2001} \u{2002}\u{2007}\u{3000}swift-tools-vErsion:\u{A0}\u{1680}\t\u{2000}6.1.2;;;;;" : (6, 1, 2, "6.1.2"), - "\u{2029}//\u{202F}\u{3000}swift-tools-version:\u{A0}\u{1680}\t\u{2000}\u{2001} \u{2002}6.1.2;x;x;x;x;x;" : (6, 1, 2, "6.1.2"), - "\u{A}\u{D}\u{85}\u{202F}\u{2029}\u{A}\u{2028}//\u{2000}\u{2001}\u{9}swift-toolS-version:\u{A0}\u{1680}\t\u{2000}\u{2009} \u{2002}\u{202F}5.5.2;hello" : (5, 5, 2, "5.5.2"), - "\u{D}\u{A}\t\u{85}\u{85}\u{A}\u{2028}\u{2029}//\u{2001}\u{2002}\u{202F}sWiFt-tOoLs-vErSiOn:\u{1680}\t\u{2000}\u{200A} \u{2002}\u{202F}5.5.2\nkkk\n" : (5, 5, 2, "5.5.2"), + "\u{2002}\u{202F}\u{A}//\u{A0}\u{1680}\t\u{2004}\u{2001} \u{2002}swift-tools-version:\u{3000}5.4.0": (5, 4, 0, "5.4.0"), + "\u{B}//\u{A0}\u{1680}\t\u{2000}\u{2001} \u{2002}swift-tools-version:\u{202F}\u{3000}5.4-dev": (5, 4, 0, "5.4.0"), + "\u{C}//\u{A0}\u{1680}\t\u{2000}\u{2001} swift-tools-version:\u{2002}\u{202F}\u{3000}5.8.0": (5, 8, 0, "5.8.0"), + "\u{D}//\u{A0}\u{1680}\t\u{2005} \u{202F}\u{3000}swift-tools-version:\u{2001}5.8.0-dev.al+sha.x": (5, 8, 0, "5.8.0"), + "\u{D}\u{A}//\u{A0}\u{2001} \u{2002}\u{202F}\u{3000}swift-tools-version:\u{1680}\t\u{2000}6.1.2": (6, 1, 2, "6.1.2"), + "\u{85}//\u{2000}\u{2001} \u{2006}\u{202F}\u{3000}swift-tools-version:\u{A0}\u{1680}\t6.1.2;": (6, 1, 2, "6.1.2"), + "\u{2028}//\u{2001} \u{2002}\u{2007}\u{3000}swift-tools-vErsion:\u{A0}\u{1680}\t\u{2000}6.1.2;;;;;": (6, 1, 2, "6.1.2"), + "\u{2029}//\u{202F}\u{3000}swift-tools-version:\u{A0}\u{1680}\t\u{2000}\u{2001} \u{2002}6.1.2;x;x;x;x;x;": (6, 1, 2, "6.1.2"), + "\u{A}\u{D}\u{85}\u{202F}\u{2029}\u{A}\u{2028}//\u{2000}\u{2001}\u{9}swift-toolS-version:\u{A0}\u{1680}\t\u{2000}\u{2009} \u{2002}\u{202F}5.5.2;hello": (5, 5, 2, "5.5.2"), + "\u{D}\u{A}\t\u{85}\u{85}\u{A}\u{2028}\u{2029}//\u{2001}\u{2002}\u{202F}sWiFt-tOoLs-vErSiOn:\u{1680}\t\u{2000}\u{200A} \u{2002}\u{202F}5.5.2\nkkk\n": (5, 5, 2, "5.5.2"), ] for (snippet, result) in manifestsSnippetWithValidVersionSpecification { @@ -113,7 +113,6 @@ final class ToolsVersionParserTests: XCTestCase { } } - do { try self.parse( """ @@ -148,26 +147,26 @@ final class ToolsVersionParserTests: XCTestCase { func testToolsVersionAllowsComments() throws { try self.parse( - """ - // comment 1 - // comment 2 - // swift-tools-version: 6.0 - // comment - let package = .. - """ - ) { toolsVersion in - XCTAssertEqual(toolsVersion.description, "6.0.0") - } - - do { - try self.parse( """ // comment 1 // comment 2 - // swift-tools-version:5.0 + // swift-tools-version: 6.0 // comment let package = .. """ + ) { toolsVersion in + XCTAssertEqual(toolsVersion.description, "6.0.0") + } + + do { + try self.parse( + """ + // comment 1 + // comment 2 + // swift-tools-version:5.0 + // comment + let package = .. + """ ) { _ in XCTFail("expected an error to be thrown") } @@ -179,11 +178,11 @@ final class ToolsVersionParserTests: XCTestCase { do { try self.parse( - """ - // comment 1 - // comment 2 - let package = .. - """ + """ + // comment 1 + // comment 2 + let package = .. + """ ) { _ in XCTFail("expected an error to be thrown") } @@ -194,14 +193,14 @@ final class ToolsVersionParserTests: XCTestCase { } try self.parse( - """ - /* - this is a multiline comment - */ - // swift-tools-version: 6.0 - // comment - let package = .. - """ + """ + /* + this is a multiline comment + */ + // swift-tools-version: 6.0 + // comment + let package = .. + """ ) { toolsVersion in XCTAssertEqual(toolsVersion.description, "6.0.0") } @@ -211,27 +210,28 @@ final class ToolsVersionParserTests: XCTestCase { func testEmptyManifest() throws { let fs = InMemoryFileSystem() - let packageRoot = AbsolutePath("/lorem/ipsum/dolor") - try fs.createDirectory(packageRoot, recursive: true) + let packageRoot = AbsolutePath("/lorem/ipsum/dolor") + try fs.createDirectory(packageRoot, recursive: true) - let manifestPath = packageRoot.appending("Package.swift") + let manifestPath = packageRoot.appending("Package.swift") try fs.writeFileContents(manifestPath, bytes: "") XCTAssertThrowsError( try ToolsVersionParser.parse(manifestPath: manifestPath, fileSystem: fs), - "empty manifest '\(manifestPath.pathString)'") { error in - guard let error = error as? ManifestParseError, case .emptyManifest(let errorPath) = error else { - XCTFail("'ManifestParseError.emptyManifest' should've been thrown, but a different error is thrown") - return - } - - guard errorPath == manifestPath else { - XCTFail("error is in '\(manifestPath)', but '\(errorPath)' is given for the error message") - return - } + "empty manifest '\(manifestPath.pathString)'" + ) { error in + guard let error = error as? ManifestParseError, case .emptyManifest(let errorPath) = error else { + XCTFail("'ManifestParseError.emptyManifest' should've been thrown, but a different error is thrown") + return + } - XCTAssertEqual(error.description, "'\(manifestPath._nativePathString(escaped: false))' is empty") + guard errorPath == manifestPath else { + XCTFail("error is in '\(manifestPath)', but '\(errorPath)' is given for the error message") + return } + + XCTAssertEqual(error.description, "'\(manifestPath._nativePathString(escaped: false))' is empty") + } } /// Verifies that the correct error is thrown for each non-empty manifest missing its Swift tools version specification. @@ -472,19 +472,19 @@ final class ToolsVersionParserTests: XCTestCase { // MARK: 1 leading u+000D let manifestSnippetWith1LeadingCarriageReturn = [ - "\u{D}//swift-tools-version:3.1" : "3.1.0", - "\u{D}//swift-tools-version:3.1-dev" : "3.1.0", - "\u{D}//swift-tools-version:5.3" : "5.3.0", - "\u{D}//swift-tools-version:5.3.0" : "5.3.0", - "\u{D}//swift-tools-version:5.3-dev" : "5.3.0", - "\u{D}//swift-tools-version:4.8.0" : "4.8.0", - "\u{D}//swift-tools-version:4.8.0-dev.al+sha.x" : "4.8.0", - "\u{D}//swift-tools-version:3.1.2" : "3.1.2", - "\u{D}//swift-tools-version:3.1.2;" : "3.1.2", - "\u{D}//swift-tools-vErsion:3.1.2;;;;;" : "3.1.2", - "\u{D}//swift-tools-version:3.1.2;x;x;x;x;x;" : "3.1.2", - "\u{D}//swift-toolS-version:3.5.2;hello" : "3.5.2", - "\u{D}//sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n" : "3.5.2", + "\u{D}//swift-tools-version:3.1": "3.1.0", + "\u{D}//swift-tools-version:3.1-dev": "3.1.0", + "\u{D}//swift-tools-version:5.3": "5.3.0", + "\u{D}//swift-tools-version:5.3.0": "5.3.0", + "\u{D}//swift-tools-version:5.3-dev": "5.3.0", + "\u{D}//swift-tools-version:4.8.0": "4.8.0", + "\u{D}//swift-tools-version:4.8.0-dev.al+sha.x": "4.8.0", + "\u{D}//swift-tools-version:3.1.2": "3.1.2", + "\u{D}//swift-tools-version:3.1.2;": "3.1.2", + "\u{D}//swift-tools-vErsion:3.1.2;;;;;": "3.1.2", + "\u{D}//swift-tools-version:3.1.2;x;x;x;x;x;": "3.1.2", + "\u{D}//swift-toolS-version:3.5.2;hello": "3.5.2", + "\u{D}//sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n": "3.5.2", ] for (specification, toolsVersionString) in manifestSnippetWith1LeadingCarriageReturn { @@ -506,19 +506,19 @@ final class ToolsVersionParserTests: XCTestCase { // MARK: 1 U+0020 let manifestSnippetWith1LeadingSpace = [ - "\u{20}//swift-tools-version:3.1" : "3.1.0", - "\u{20}//swift-tools-version:3.1-dev" : "3.1.0", - "\u{20}//swift-tools-version:5.3" : "5.3.0", - "\u{20}//swift-tools-version:5.3.0" : "5.3.0", - "\u{20}//swift-tools-version:5.3-dev" : "5.3.0", - "\u{20}//swift-tools-version:4.8.0" : "4.8.0", - "\u{20}//swift-tools-version:4.8.0-dev.al+sha.x" : "4.8.0", - "\u{20}//swift-tools-version:3.1.2" : "3.1.2", - "\u{20}//swift-tools-version:3.1.2;" : "3.1.2", - "\u{20}//swift-tools-vErsion:3.1.2;;;;;" : "3.1.2", - "\u{20}//swift-tools-version:3.1.2;x;x;x;x;x;" : "3.1.2", - "\u{20}//swift-toolS-version:3.5.2;hello" : "3.5.2", - "\u{20}//sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n" : "3.5.2", + "\u{20}//swift-tools-version:3.1": "3.1.0", + "\u{20}//swift-tools-version:3.1-dev": "3.1.0", + "\u{20}//swift-tools-version:5.3": "5.3.0", + "\u{20}//swift-tools-version:5.3.0": "5.3.0", + "\u{20}//swift-tools-version:5.3-dev": "5.3.0", + "\u{20}//swift-tools-version:4.8.0": "4.8.0", + "\u{20}//swift-tools-version:4.8.0-dev.al+sha.x": "4.8.0", + "\u{20}//swift-tools-version:3.1.2": "3.1.2", + "\u{20}//swift-tools-version:3.1.2;": "3.1.2", + "\u{20}//swift-tools-vErsion:3.1.2;;;;;": "3.1.2", + "\u{20}//swift-tools-version:3.1.2;x;x;x;x;x;": "3.1.2", + "\u{20}//swift-toolS-version:3.5.2;hello": "3.5.2", + "\u{20}//sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n": "3.5.2", ] for (specification, toolsVersionString) in manifestSnippetWith1LeadingSpace { @@ -540,19 +540,19 @@ final class ToolsVersionParserTests: XCTestCase { // MARK: An assortment of leading whitespace characters let manifestSnippetWithAnAssortmentOfLeadingWhitespaceCharacters = [ - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1" : "3.1.0", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1-dev" : "3.1.0", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:5.3" : "5.3.0", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:5.3.0" : "5.3.0", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:5.3-dev" : "5.3.0", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:4.8.0" : "4.8.0", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:4.8.0-dev.al+sha.x" : "4.8.0", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1.2" : "3.1.2", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1.2;" : "3.1.2", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-vErsion:3.1.2;;;;;" : "3.1.2", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1.2;x;x;x;x;x;" : "3.1.2", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-toolS-version:3.5.2;hello" : "3.5.2", - "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n" : "3.5.2", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1": "3.1.0", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1-dev": "3.1.0", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:5.3": "5.3.0", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:5.3.0": "5.3.0", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:5.3-dev": "5.3.0", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:4.8.0": "4.8.0", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:4.8.0-dev.al+sha.x": "4.8.0", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1.2": "3.1.2", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1.2;": "3.1.2", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-vErsion:3.1.2;;;;;": "3.1.2", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-tools-version:3.1.2;x;x;x;x;x;": "3.1.2", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//swift-toolS-version:3.5.2;hello": "3.5.2", + "\u{A}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}\u{D}\u{D}\u{A}\u{85}\u{2001}\u{2028}\u{2002}\u{202F}\u{2029}\u{3000}//sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n": "3.5.2", ] for (specification, toolsVersionString) in manifestSnippetWithAnAssortmentOfLeadingWhitespaceCharacters { @@ -574,19 +574,19 @@ final class ToolsVersionParserTests: XCTestCase { // MARK: An assortment of leading whitespace characters and an assortment of horizontal whitespace characters surrounding the label let manifestSnippetWithAnAssortmentOfLeadingWhitespaceCharactersAndAnAssortmentOfWhitespacesSurroundingLabel = [ - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1" : "3.1.0", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1-dev" : "3.1.0", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}5.3" : "5.3.0", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}5.3.0" : "5.3.0", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}5.3-dev" : "5.3.0", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}4.8.0" : "4.8.0", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}4.8.0-dev.al+sha.x" : "4.8.0", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1.2" : "3.1.2", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1.2;" : "3.1.2", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-vErsion:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1.2;;;;;" : "3.1.2", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1.2;x;x;x;x;x;" : "3.1.2", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-toolS-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.5.2;hello" : "3.5.2", - "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}sWiFt-tOoLs-vErSiOn:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.5.2\nkkk\n" : "3.5.2", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1": "3.1.0", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1-dev": "3.1.0", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}5.3": "5.3.0", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}5.3.0": "5.3.0", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}5.3-dev": "5.3.0", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}4.8.0": "4.8.0", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}4.8.0-dev.al+sha.x": "4.8.0", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1.2": "3.1.2", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1.2;": "3.1.2", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-vErsion:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1.2;;;;;": "3.1.2", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.1.2;x;x;x;x;x;": "3.1.2", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-toolS-version:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.5.2;hello": "3.5.2", + "\u{D}\u{202F}\u{2029}\u{85}\u{2001}\u{2028}\u{3000}\u{A}\u{D}\u{A}\u{2002}\u{A0}\u{B}\u{1680}\u{C}\t\u{2000}//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}sWiFt-tOoLs-vErSiOn:\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}3.5.2\nkkk\n": "3.5.2", ] // Backward-incompatible leading whitespace is diagnosed before backward-incompatible spacings surrounding the label. @@ -610,19 +610,19 @@ final class ToolsVersionParserTests: XCTestCase { // MARK: No spacing surrounding the label let specificationsWithZeroSpacing = [ - "//swift-tools-version:3.1" : "3.1.0", - "//swift-tools-version:3.1-dev" : "3.1.0", - "//swift-tools-version:5.3" : "5.3.0", - "//swift-tools-version:5.3.0" : "5.3.0", - "//swift-tools-version:5.3-dev" : "5.3.0", - "//swift-tools-version:4.8.0" : "4.8.0", - "//swift-tools-version:4.8.0-dev.al+sha.x" : "4.8.0", - "//swift-tools-version:3.1.2" : "3.1.2", - "//swift-tools-version:3.1.2;" : "3.1.2", - "//swift-tools-vErsion:3.1.2;;;;;" : "3.1.2", - "//swift-tools-version:3.1.2;x;x;x;x;x;" : "3.1.2", - "//swift-toolS-version:3.5.2;hello" : "3.5.2", - "//sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n" : "3.5.2", + "//swift-tools-version:3.1": "3.1.0", + "//swift-tools-version:3.1-dev": "3.1.0", + "//swift-tools-version:5.3": "5.3.0", + "//swift-tools-version:5.3.0": "5.3.0", + "//swift-tools-version:5.3-dev": "5.3.0", + "//swift-tools-version:4.8.0": "4.8.0", + "//swift-tools-version:4.8.0-dev.al+sha.x": "4.8.0", + "//swift-tools-version:3.1.2": "3.1.2", + "//swift-tools-version:3.1.2;": "3.1.2", + "//swift-tools-vErsion:3.1.2;;;;;": "3.1.2", + "//swift-tools-version:3.1.2;x;x;x;x;x;": "3.1.2", + "//swift-toolS-version:3.5.2;hello": "3.5.2", + "//sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n": "3.5.2", ] for (specification, toolsVersionString) in specificationsWithZeroSpacing { @@ -644,19 +644,19 @@ final class ToolsVersionParserTests: XCTestCase { // MARK: An assortment of horizontal whitespace characters before the label let specificationsWithAnAssortmentOfWhitespacesBeforeLabel = [ - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1" : "3.1.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1-dev" : "3.1.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:5.3" : "5.3.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:5.3.0" : "5.3.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:5.3-dev" : "5.3.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:4.8.0" : "4.8.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:4.8.0-dev.al+sha.x" : "4.8.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1.2" : "3.1.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1.2;" : "3.1.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-vErsion:3.1.2;;;;;" : "3.1.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1.2;x;x;x;x;x;" : "3.1.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-toolS-version:3.5.2;hello" : "3.5.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n" : "3.5.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1": "3.1.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1-dev": "3.1.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:5.3": "5.3.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:5.3.0": "5.3.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:5.3-dev": "5.3.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:4.8.0": "4.8.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:4.8.0-dev.al+sha.x": "4.8.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1.2": "3.1.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1.2;": "3.1.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-vErsion:3.1.2;;;;;": "3.1.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-tools-version:3.1.2;x;x;x;x;x;": "3.1.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}swift-toolS-version:3.5.2;hello": "3.5.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}sWiFt-tOoLs-vErSiOn:3.5.2\nkkk\n": "3.5.2", ] for (specification, toolsVersionString) in specificationsWithAnAssortmentOfWhitespacesBeforeLabel { @@ -678,19 +678,19 @@ final class ToolsVersionParserTests: XCTestCase { // MARK: An assortment of horizontal whitespace characters surrounding the label let specificationsWithAnAssortmentOfWhitespacesBeforeAndAfterLabel = [ - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1" : "3.1.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1-dev" : "3.1.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3" : "5.3.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3.0" : "5.3.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3-dev" : "5.3.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}4.8.0" : "4.8.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}4.8.0-dev.al+sha.x" : "4.8.0", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2" : "3.1.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;" : "3.1.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-vErsion:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;;;;;" : "3.1.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;x;x;x;x;x;" : "3.1.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-toolS-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.5.2;hello" : "3.5.2", - "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}sWiFt-tOoLs-vErSiOn:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.5.2\nkkk\n" : "3.5.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1": "3.1.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1-dev": "3.1.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3": "5.3.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3.0": "5.3.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3-dev": "5.3.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}4.8.0": "4.8.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}4.8.0-dev.al+sha.x": "4.8.0", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2": "3.1.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;": "3.1.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-vErsion:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;;;;;": "3.1.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-tools-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;x;x;x;x;x;": "3.1.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}swift-toolS-version:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.5.2;hello": "3.5.2", + "//\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}sWiFt-tOoLs-vErSiOn:\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.5.2\nkkk\n": "3.5.2", ] // Backward-incompatible spacings after the comment marker is diagnosed before backward-incompatible spacings after the label. @@ -714,19 +714,19 @@ final class ToolsVersionParserTests: XCTestCase { // MARK: 1 U+0020 before the label and an assortment of horizontal whitespace characters after the label let specificationsWithAnAssortmentOfWhitespacesAfterLabel = [ - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1" : "3.1.0", - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1-dev" : "3.1.0", - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3" : "5.3.0", - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3.0" : "5.3.0", - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3-dev" : "5.3.0", - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}4.8.0" : "4.8.0", - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}4.8.0-dev.al+sha.x" : "4.8.0", - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2" : "3.1.2", - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;" : "3.1.2", - "// swift-tools-vErsion:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;;;;;" : "3.1.2", - "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;x;x;x;x;x;" : "3.1.2", - "// swift-toolS-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.5.2;hello" : "3.5.2", - "// sWiFt-tOoLs-vErSiOn:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.5.2\nkkk\n" : "3.5.2", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1": "3.1.0", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1-dev": "3.1.0", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3": "5.3.0", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3.0": "5.3.0", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}5.3-dev": "5.3.0", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}4.8.0": "4.8.0", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}4.8.0-dev.al+sha.x": "4.8.0", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2": "3.1.2", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;": "3.1.2", + "// swift-tools-vErsion:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;;;;;": "3.1.2", + "// swift-tools-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.1.2;x;x;x;x;x;": "3.1.2", + "// swift-toolS-version:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.5.2;hello": "3.5.2", + "// sWiFt-tOoLs-vErSiOn:\u{9}\u{20}\u{A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{202F}\u{205F}\u{3000}3.5.2\nkkk\n": "3.5.2", ] for (specification, toolsVersionString) in specificationsWithAnAssortmentOfWhitespacesAfterLabel { @@ -789,8 +789,9 @@ final class ToolsVersionParserTests: XCTestCase { } func testVersionSpecificManifestFallbacks() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/pkg/foo" + let fs = InMemoryFileSystem( + emptyFiles: + "/pkg/foo" ) let root = AbsolutePath("/pkg") @@ -823,8 +824,9 @@ final class ToolsVersionParserTests: XCTestCase { } func testVersionSpecificManifestMostCompatibleIfLower() throws { - let fs = InMemoryFileSystem(emptyFiles: - "/pkg/foo" + let fs = InMemoryFileSystem( + emptyFiles: + "/pkg/foo" ) let root = AbsolutePath("/pkg") diff --git a/Tests/PackageLoadingTests/TraitLoadingTests.swift b/Tests/PackageLoadingTests/TraitLoadingTests.swift index 6f2378fd694..f3e518ae044 100644 --- a/Tests/PackageLoadingTests/TraitLoadingTests.swift +++ b/Tests/PackageLoadingTests/TraitLoadingTests.swift @@ -22,7 +22,7 @@ final class TraitLoadingTests: PackageDescriptionLoadingTests { } func testTraits() async throws { - let content = """ + let content = """ import PackageDescription let package = Package( name: "Foo", @@ -39,16 +39,19 @@ final class TraitLoadingTests: PackageDescriptionLoadingTests { XCTAssertNoDiagnostics(observability.diagnostics) XCTAssertNoDiagnostics(validationDiagnostics) - XCTAssertEqual(manifest.traits, [ - TraitDescription(name: "Trait1"), - TraitDescription(name: "Trait2", description: "Trait 2 description"), - TraitDescription(name: "Trait3", description: "Trait 3 description", enabledTraits: ["Trait1"]), - ]) + XCTAssertEqual( + manifest.traits, + [ + TraitDescription(name: "Trait1"), + TraitDescription(name: "Trait2", description: "Trait 2 description"), + TraitDescription(name: "Trait3", description: "Trait 3 description", enabledTraits: ["Trait1"]), + ] + ) } func testTraits_whenTooMany() async throws { let traits = Array(0...300).map { "\"Trait\($0)\"" }.joined(separator: ",") - let content = """ + let content = """ import PackageDescription let package = Package( name: "Foo", @@ -65,7 +68,7 @@ final class TraitLoadingTests: PackageDescriptionLoadingTests { } func testTraits_whenUnknownEnabledTrait() async throws { - let content = """ + let content = """ import PackageDescription let package = Package( name: "Foo", @@ -97,15 +100,15 @@ final class TraitLoadingTests: PackageDescriptionLoadingTests { ] for traitName in invalidTraitNames { - let content = """ - import PackageDescription - let package = Package( - name: "Foo", - traits: [ - "\(traitName)" - ] - ) - """ + let content = """ + import PackageDescription + let package = Package( + name: "Foo", + traits: [ + "\(traitName)" + ] + ) + """ let observability = ObservabilitySystem.makeForTesting() let (_, validationDiagnostics) = try await loadAndValidateManifest(content, observabilityScope: observability.topScope) @@ -130,15 +133,15 @@ final class TraitLoadingTests: PackageDescriptionLoadingTests { ] for traitName in invalidTraitNames { - let content = """ - import PackageDescription - let package = Package( - name: "Foo", - traits: [ - "\(traitName)" - ] - ) - """ + let content = """ + import PackageDescription + let package = Package( + name: "Foo", + traits: [ + "\(traitName)" + ] + ) + """ let observability = ObservabilitySystem.makeForTesting() let (_, validationDiagnostics) = try await loadAndValidateManifest(content, observabilityScope: observability.topScope) @@ -149,7 +152,7 @@ final class TraitLoadingTests: PackageDescriptionLoadingTests { } func testDefaultTraits() async throws { - let content = """ + let content = """ import PackageDescription let package = Package( name: "Foo", @@ -167,16 +170,19 @@ final class TraitLoadingTests: PackageDescriptionLoadingTests { XCTAssertNoDiagnostics(observability.diagnostics) XCTAssertNoDiagnostics(validationDiagnostics) - XCTAssertEqual(manifest.traits, [ - TraitDescription(name: "default", description: "The default traits of this package.", enabledTraits: ["Trait1", "Trait3"]), - TraitDescription(name: "Trait1"), - TraitDescription(name: "Trait2"), - TraitDescription(name: "Trait3", enabledTraits: ["Trait1"]), - ]) + XCTAssertEqual( + manifest.traits, + [ + TraitDescription(name: "default", description: "The default traits of this package.", enabledTraits: ["Trait1", "Trait3"]), + TraitDescription(name: "Trait1"), + TraitDescription(name: "Trait2"), + TraitDescription(name: "Trait3", enabledTraits: ["Trait1"]), + ] + ) } func testDependencies() async throws { - let content = """ + let content = """ import PackageDescription let package = Package( name: "Foo", @@ -246,12 +252,15 @@ final class TraitLoadingTests: PackageDescriptionLoadingTests { XCTAssertNoDiagnostics(observability.diagnostics) XCTAssertNoDiagnostics(validationDiagnostics) - XCTAssertEqual(manifest.traits, [ - TraitDescription(name: "default", description: "The default traits of this package.", enabledTraits: ["Trait1", "Trait2"]), - TraitDescription(name: "Trait1"), - TraitDescription(name: "Trait2"), - ]) - let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map{ ($0.identity.description, $0) }) + XCTAssertEqual( + manifest.traits, + [ + TraitDescription(name: "default", description: "The default traits of this package.", enabledTraits: ["Trait1", "Trait2"]), + TraitDescription(name: "Trait1"), + TraitDescription(name: "Trait2"), + ] + ) + let deps = Dictionary(uniqueKeysWithValues: manifest.dependencies.map { ($0.identity.description, $0) }) XCTAssertEqual( deps["x.foo"]?.traits, [ diff --git a/Tests/PackageModelTests/CanonicalPackageLocationTests.swift b/Tests/PackageModelTests/CanonicalPackageLocationTests.swift index f53d765d0b0..b39f8f73290 100644 --- a/Tests/PackageModelTests/CanonicalPackageLocationTests.swift +++ b/Tests/PackageModelTests/CanonicalPackageLocationTests.swift @@ -29,19 +29,19 @@ final class CanonicalPackageLocationTests: XCTestCase { func testNormalizationInsensitivity() { XCTAssertEqual( - CanonicalPackageLocation("mona/e\u{0301}clair").description, // ◌́ COMBINING ACUTE ACCENT (U+0301) + CanonicalPackageLocation("mona/e\u{0301}clair").description, // ◌́ COMBINING ACUTE ACCENT (U+0301) "mona/éclair" ) XCTAssertEqual( - CanonicalPackageLocation("mona/\u{00C9}clair").description, // LATIN CAPITAL LETTER E WITH ACUTE (U+00C9) + CanonicalPackageLocation("mona/\u{00C9}clair").description, // LATIN CAPITAL LETTER E WITH ACUTE (U+00C9) "mona/éclair" ) } func testCaseAndNormalizationInsensitivity() { XCTAssertEqual( - CanonicalPackageLocation("mona/E\u{0301}clair").description, // ◌́ COMBINING ACUTE ACCENT (U+0301) + CanonicalPackageLocation("mona/E\u{0301}clair").description, // ◌́ COMBINING ACUTE ACCENT (U+0301) "mona/éclair" ) } diff --git a/Tests/PackageModelTests/EnabledTraitTests.swift b/Tests/PackageModelTests/EnabledTraitTests.swift index 35b8a5fc7f7..a4802dcd1b7 100644 --- a/Tests/PackageModelTests/EnabledTraitTests.swift +++ b/Tests/PackageModelTests/EnabledTraitTests.swift @@ -47,7 +47,7 @@ struct EnabledTraitTests { let unifiedBananaTrait = try #require(bananaTraitSetByBread.unify(bananaTraitSetByFruit)) let setters: Set = [ EnabledTrait.Setter.package(.init(identity: "Fruit")), - EnabledTrait.Setter.trait(.init("Bread")) + EnabledTrait.Setter.trait(.init("Bread")), ] #expect(unifiedBananaTrait.setters == setters) @@ -72,8 +72,8 @@ struct EnabledTraitTests { func enabledTrait_compareToStringLiteral() { let appleTrait = EnabledTrait(name: "Apple", setBy: .default) - #expect("Apple" == appleTrait) // test when EnabledTrait rhs - #expect(appleTrait == "Apple") // test when EnabledTrait lhs + #expect("Apple" == appleTrait) // test when EnabledTrait rhs + #expect(appleTrait == "Apple") // test when EnabledTrait lhs } /// Tests that `EnabledTrait` can be compared to a `String` for equality in both @@ -83,8 +83,8 @@ struct EnabledTraitTests { let appleTrait = EnabledTrait(name: "Apple", setBy: .default) let stringTrait = "Apple" - #expect(stringTrait.asEnabledTrait == appleTrait) // test when EnabledTrait rhs - #expect(appleTrait == stringTrait.asEnabledTrait) // test when EnabledTrait lhs + #expect(stringTrait.asEnabledTrait == appleTrait) // test when EnabledTrait rhs + #expect(appleTrait == stringTrait.asEnabledTrait) // test when EnabledTrait lhs } /// Verifies that an `EnabledTrait` can be initialized using a string literal and is @@ -139,11 +139,12 @@ struct EnabledTraitTests { name: "Coffee", setBy: [ .package(.init(identity: "Cafe")), - .package(.init(identity:"Home")), + .package(.init(identity: "Home")), .package(.init(identity: "Breakfast")), .trait("NotAPackage"), - .traitConfiguration - ]) + .traitConfiguration, + ] + ) let parentPackagesFromTrait = traitSetByPackages.parentPackages @@ -161,7 +162,7 @@ struct EnabledTraitTests { let toTestAgainst = EnabledTraits([ EnabledTrait(name: "One", setBy: .default), EnabledTrait(name: "Two", setBy: .default), - EnabledTrait(name: "Three", setBy: .default) + EnabledTrait(name: "Three", setBy: .default), ]) #expect(enabledTraits == toTestAgainst) @@ -212,7 +213,6 @@ struct EnabledTraitTests { #expect(enabledTraits.count == 3) #expect(enabledTraits == ["Apple", "Banana", "Orange"]) - // Assure that Apple trait is removed and returned let appleTrait = enabledTraits.remove("Apple") let unwrappedAppleTrait = try #require(appleTrait) @@ -236,7 +236,6 @@ struct EnabledTraitTests { let newTrait = EnabledTrait(name: "Apple", setBy: [.package(.init(identity: "Fruit")), .trait("FavouriteFruit")]) - // Try to remove Apple trait before inserting: #expect(enabledTraits.remove("Apple") == nil) #expect(enabledTraits.count == 1) @@ -258,11 +257,12 @@ struct EnabledTraitTests { }) #expect( - transformedTraits == EnabledTraits([ - EnabledTrait(name: "Apple", setBy: .package(.init(identity: "Breakfast"))), - EnabledTrait(name: "Coffee", setBy: .package(.init(identity: "Breakfast"))), - EnabledTrait(name: "Cookie", setBy: .package(.init(identity: "Breakfast"))) - ]) + transformedTraits + == EnabledTraits([ + EnabledTrait(name: "Apple", setBy: .package(.init(identity: "Breakfast"))), + EnabledTrait(name: "Coffee", setBy: .package(.init(identity: "Breakfast"))), + EnabledTrait(name: "Cookie", setBy: .package(.init(identity: "Breakfast"))), + ]) ) } @@ -285,12 +285,12 @@ struct EnabledTraitTests { func enabledTraits_unionWithExistingTraits() throws { let enabledTraits: EnabledTraits = [ EnabledTrait(name: "Banana", setBy: .default), - EnabledTrait(name: "Apple", setBy: .package(.init(identity: "MyFruits"))) + EnabledTrait(name: "Apple", setBy: .package(.init(identity: "MyFruits"))), ] let newTraits: EnabledTraits = [ EnabledTrait(name: "Banana", setBy: [.package(.init(identity: "OtherFruits")), .trait("Bread")]), EnabledTrait(name: "Apple", setBy: .default), - "Milkshake" + "Milkshake", ] var unifiedSetOfTraits = enabledTraits.union(newTraits) @@ -304,20 +304,22 @@ struct EnabledTraitTests { #expect(unifiedSetOfTraits.count == 2) #expect( - bananaTrait.setters == Set([ - .package(.init(identity: "OtherFruits")), - .trait("Bread"), - .default - ]) + bananaTrait.setters + == Set([ + .package(.init(identity: "OtherFruits")), + .trait("Bread"), + .default, + ]) ) let appleTrait = try unifiedSetOfTraits.unwrapRemove(EnabledTrait(name: "Apple", setBy: .default)) #expect(unifiedSetOfTraits.count == 1) #expect( - appleTrait.setters == Set([ - .package(.init(identity: "MyFruits")), - .default - ]) + appleTrait.setters + == Set([ + .package(.init(identity: "MyFruits")), + .default, + ]) ) let milkshakeTrait = try unifiedSetOfTraits.unwrapRemove("Milkshake") @@ -332,7 +334,7 @@ struct EnabledTraitTests { var traits: EnabledTraits = [ "Banana", EnabledTrait(name: "Banana", setBy: .default), - "Chocolate" + "Chocolate", ] #expect(traits.count == 2) @@ -373,7 +375,7 @@ struct EnabledTraitTests { let enabledTraits: EnabledTraits = ["Apple", "Banana", "Orange"] var otherEnabledTraits: EnabledTraits = ["Banana", "Chocolate"] #expect(enabledTraits != otherEnabledTraits) - + let intersection = enabledTraits.intersection(otherEnabledTraits) #expect(intersection.count == 1) #expect(intersection.contains("Banana")) @@ -455,7 +457,7 @@ struct EnabledTraitTests { func enabledTraitsMap_initWithDictionaryLiteral() { let map: EnabledTraitsMap = [ "PackageA": ["Apple", "Banana"], - "PackageB": ["Coffee"] + "PackageB": ["Coffee"], ] #expect(map["PackageA"] == ["Apple", "Banana"]) @@ -467,7 +469,7 @@ struct EnabledTraitTests { func enabledTraitsMap_initWithDictionary() { let dictionary: [String: EnabledTraits] = [ "PackageA": ["Apple", "Banana"], - "PackageB": ["Coffee"] + "PackageB": ["Coffee"], ] let map = EnabledTraitsMap(dictionary) @@ -992,7 +994,6 @@ struct EnabledTraitTests { } } - // MARK: - Test Helpers extension EnabledTraits { /// Helper method that removes a trait from the set and unwraps the returned optional. diff --git a/Tests/PackageModelTests/ManifestTests.swift b/Tests/PackageModelTests/ManifestTests.swift index 0a0b6195a22..6c60bbd8550 100644 --- a/Tests/PackageModelTests/ManifestTests.swift +++ b/Tests/PackageModelTests/ManifestTests.swift @@ -38,13 +38,16 @@ class ManifestTests: XCTestCase { targets: targets ) - XCTAssertEqual(manifest.targetsRequired(for: .everything).map(\.name).sorted(), [ - "Bar", - "Baz", - "Foo", - "FooBar", - "MyPlugin", - ]) + XCTAssertEqual( + manifest.targetsRequired(for: .everything).map(\.name).sorted(), + [ + "Bar", + "Baz", + "Foo", + "FooBar", + "MyPlugin", + ] + ) } do { @@ -56,12 +59,15 @@ class ManifestTests: XCTestCase { targets: targets ) - XCTAssertEqual(manifest.targetsRequired(for: .specific(["Foo", "Bar"])).map(\.name).sorted(), [ - "Bar", - "Baz", - "Foo", - "MyPlugin", - ]) + XCTAssertEqual( + manifest.targetsRequired(for: .specific(["Foo", "Bar"])).map(\.name).sorted(), + [ + "Bar", + "Baz", + "Foo", + "MyPlugin", + ] + ) } } @@ -73,7 +79,7 @@ class ManifestTests: XCTestCase { ] let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo1"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo1"]) ] let targets = try [ @@ -115,9 +121,9 @@ class ManifestTests: XCTestCase { XCTAssertEqual( try manifest.dependenciesRequired(for: .specific(["Foo"])).map(\.identity.description).sorted(), [ - "bar1", // Foo → Foo1 → Bar1 - "bar2", // Foo → Foo1 → Foo2 → Bar2 - "bar3", // Foo → Foo1 → Bar1 → could be from any package due to pre‐5.2 tools version. + "bar1", // Foo → Foo1 → Bar1 + "bar2", // Foo → Foo1 → Foo2 → Bar2 + "bar3", // Foo → Foo1 → Bar1 → could be from any package due to pre‐5.2 tools version. ] ) } @@ -153,14 +159,14 @@ class ManifestTests: XCTestCase { ) #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - XCTAssertEqual( - manifest.dependenciesRequired(for: .specific(["Foo"]), nil).map(\.identity.description).sorted(), - [ - "bar1", // Foo → Foo1 → Bar1 - "bar2", // Foo → Foo1 → Foo2 → Bar2 - // (Bar3 is unreachable.) - ] - ) + XCTAssertEqual( + manifest.dependenciesRequired(for: .specific(["Foo"]), nil).map(\.identity.description).sorted(), + [ + "bar1", // Foo → Foo1 → Bar1 + "bar2", // Foo → Foo1 → Foo2 → Bar2 + // (Bar3 is unreachable.) + ] + ) #endif } } @@ -199,18 +205,21 @@ class ManifestTests: XCTestCase { products: products, targets: targets, traits: [], - pruneDependencies: true // Since all dependencies are used, this shouldn't affect the outcome. + pruneDependencies: true // Since all dependencies are used, this shouldn't affect the outcome. ) let enabledTraits = EnabledTraits(traits.map(\.name), setBy: .traitConfiguration) for trait in traits.sorted(by: { $0.name < $1.name }) { XCTAssertThrowsError(try manifest.isTraitEnabled(trait, enabledTraits)) { error in - XCTAssertEqual("\(error)", """ - Trait '\( + XCTAssertEqual( + "\(error)", + """ + Trait '\( trait .name - )' is not declared by package 'foo' (Foo). There are no available traits declared by this package. - """) + )' is not declared by package 'foo' (Foo). There are no available traits declared by this package. + """ + ) } } } @@ -250,35 +259,47 @@ class ManifestTests: XCTestCase { products: products, targets: targets, traits: traits, - pruneDependencies: true // Since all dependencies are used, this shouldn't affect the outcome. + pruneDependencies: true // Since all dependencies are used, this shouldn't affect the outcome. ) // Test `isTraitEnabled` when the trait we're querying for does not exist. XCTAssertThrowsError(try manifest.isTraitEnabled(.init(stringLiteral: "IDontExist"), ["default"])) { error in - XCTAssertEqual("\(error)", """ - Trait 'IDontExist' is not declared by package 'foo' (Foo). The available traits declared by this package are: Trait1, Trait2. - """) + XCTAssertEqual( + "\(error)", + """ + Trait 'IDontExist' is not declared by package 'foo' (Foo). The available traits declared by this package are: Trait1, Trait2. + """ + ) } // Test `isTraitEnabled` when the set of enabled traits contains a trait that isn't defined in the package. XCTAssertThrowsError(try manifest.isTraitEnabled(.init(stringLiteral: "Trait1"), ["IDontExist"])) { error in - XCTAssertEqual("\(error)", """ - Trait 'IDontExist' is not declared by package 'foo' (Foo). The available traits declared by this package are: Trait1, Trait2. - """) + XCTAssertEqual( + "\(error)", + """ + Trait 'IDontExist' is not declared by package 'foo' (Foo). The available traits declared by this package are: Trait1, Trait2. + """ + ) } // Test `isTraitEnabled` when the set of enabled traits contains a trait that isn't defined in the package, and the queried trait is the same non-existant trait. XCTAssertThrowsError(try manifest.isTraitEnabled(.init(stringLiteral: "IDontExist"), ["IDontExist"])) { error in - XCTAssertEqual("\(error)", """ - Trait 'IDontExist' is not declared by package 'foo' (Foo). The available traits declared by this package are: Trait1, Trait2. - """) + XCTAssertEqual( + "\(error)", + """ + Trait 'IDontExist' is not declared by package 'foo' (Foo). The available traits declared by this package are: Trait1, Trait2. + """ + ) } // Test `isTraitEnabled` when the set of enabled traits contains a trait that isn't defined in the package, and the queried trait is another non-existant trait. XCTAssertThrowsError(try manifest.isTraitEnabled(.init(stringLiteral: "IDontExistPart2"), ["IDontExist"])) { error in - XCTAssertEqual("\(error)", """ - Trait 'IDontExistPart2' is not declared by package 'foo' (Foo). The available traits declared by this package are: Trait1, Trait2. - """) + XCTAssertEqual( + "\(error)", + """ + Trait 'IDontExistPart2' is not declared by package 'foo' (Foo). The available traits declared by this package are: Trait1, Trait2. + """ + ) } } @@ -313,23 +334,29 @@ class ManifestTests: XCTestCase { products: products, targets: targets, traits: [], - pruneDependencies: true // Since all dependencies are used, this shouldn't affect the outcome. + pruneDependencies: true // Since all dependencies are used, this shouldn't affect the outcome. ) // Enabled Traits when passed a TraitConfiguration: // When passed .disableAllTraits configuration XCTAssertThrowsError(try manifest.enabledTraits(using: .disableAllTraits)) { error in - XCTAssertEqual("\(error)", """ + XCTAssertEqual( + "\(error)", + """ Disabled default traits by command-line trait configuration on package 'foo' (Foo) that declares no traits. This is prohibited to allow packages to adopt traits initially without causing an API break. - """) + """ + ) } // When passed .enableAllTraits configuration XCTAssertThrowsError(try manifest.enabledTraits(using: .enabledTraits(["Trait1"]))) { error in - XCTAssertEqual("\(error)", """ + XCTAssertEqual( + "\(error)", + """ Traits [Trait1] have been enabled on package 'foo' (Foo) that declares no traits. - """) + """ + ) } XCTAssertNoThrow(try manifest.enabledTraits(using: .enableAllTraits)) @@ -339,16 +366,22 @@ class ManifestTests: XCTestCase { // If given a parent package, and the enabled traits being passed don't exist: XCTAssertThrowsError(try manifest.enabledTraits(using: [EnabledTrait(name: "Trait1", setBy: .package(.init(identity: "qux")))])) { error in - XCTAssertEqual("\(error)", """ + XCTAssertEqual( + "\(error)", + """ Package 'qux' enables traits [Trait1] on package 'foo' (Foo) that declares no traits. - """) + """ + ) } // If given a parent package, and the default traits are disabled: XCTAssertThrowsError(try manifest.enabledTraits(using: .init([], setBy: .package("qux")))) { error in - XCTAssertEqual("\(error)", """ + XCTAssertEqual( + "\(error)", + """ Disabled default traits by package 'qux' on package 'foo' (Foo) that declares no traits. This is prohibited to allow packages to adopt traits initially without causing an API break. - """) + """ + ) } } } @@ -393,7 +426,7 @@ class ManifestTests: XCTestCase { XCTAssertEqual( try manifest.dependenciesRequired(for: .everything).map(\.identity.description).sorted(), [ - "buzz", + "buzz" ] ) @@ -418,7 +451,7 @@ class ManifestTests: XCTestCase { XCTAssertEqual( try manifestPrunedDeps.dependenciesRequired(for: .everything).map(\.identity.description).sorted(), [ - "buzz", + "buzz" ] ) @@ -493,7 +526,7 @@ class ManifestTests: XCTestCase { let traits: Set = [ TraitDescription(name: "Trait1", enabledTraits: ["Trait2"]), TraitDescription(name: "Trait2"), - TraitDescription(name: "Trait3") + TraitDescription(name: "Trait3"), ] do { @@ -505,19 +538,21 @@ class ManifestTests: XCTestCase { products: products, targets: targets, traits: traits, - pruneDependencies: true // Since all dependencies are used, this shouldn't affect the outcome. + pruneDependencies: true // Since all dependencies are used, this shouldn't affect the outcome. ) - XCTAssertNoThrow(try { - let enabledTraits = try XCTUnwrap(manifest.enabledTraits(using: .disableAllTraits)) - XCTAssertEqual(enabledTraits, []) - }()) + XCTAssertNoThrow( + try { + let enabledTraits = try XCTUnwrap(manifest.enabledTraits(using: .disableAllTraits)) + XCTAssertEqual(enabledTraits, []) + }() + ) } } func testEnabledTraits_WithOnlyDefaultTraitsEnabled() throws { let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ] let targets = try [ @@ -552,7 +587,7 @@ class ManifestTests: XCTestCase { func testEnabledTraits_WithExplicitTraitsEnabled() throws { let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ] let targets = try [ @@ -592,7 +627,7 @@ class ManifestTests: XCTestCase { func testEnabledTraits_WithAllTraitsEnabled() throws { let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ] let targets = try [ @@ -630,7 +665,7 @@ class ManifestTests: XCTestCase { ] let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ] let targets = try [ @@ -649,9 +684,9 @@ class ManifestTests: XCTestCase { .product( name: "Bar2", package: "Bar" - ) + ), ] - ), + ) ] let traits: Set = [ @@ -693,7 +728,7 @@ class ManifestTests: XCTestCase { ] let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ] let unguardedTargetDependency: TargetDescription.Dependency = .product( @@ -731,7 +766,7 @@ class ManifestTests: XCTestCase { trait3GuardedTargetDependency, defaultTraitGuardedTargetDependency, enabledTargetDependencyWithSamePackage, - manyTraitsEnableTargetDependency + manyTraitsEnableTargetDependency, ] ) @@ -756,85 +791,109 @@ class ManifestTests: XCTestCase { ) // Test if an unguarded target dependency is enabled; should be true. - XCTAssertTrue(try manifest.isTargetDependencyEnabled( - target: "Foo", - unguardedTargetDependency, - enabledTraits: ["default"] - )) + XCTAssertTrue( + try manifest.isTargetDependencyEnabled( + target: "Foo", + unguardedTargetDependency, + enabledTraits: ["default"] + ) + ) // Test if a trait-guarded dependency is enabled when passed a set of enabled traits that // unblock this target dependency; should be true. - XCTAssertTrue(try manifest.isTargetDependencyEnabled( - target: "Foo", - trait3GuardedTargetDependency, - enabledTraits: ["Trait3"] - )) + XCTAssertTrue( + try manifest.isTargetDependencyEnabled( + target: "Foo", + trait3GuardedTargetDependency, + enabledTraits: ["Trait3"] + ) + ) // Test if a trait-guarded dependency is enabled when passed all traits enabled; // should be true. - XCTAssertTrue(try manifest.isTargetDependencyEnabled( - target: "Foo", - trait3GuardedTargetDependency, - enabledTraits: ["Trait1", "Trait2", "Trait3"] - )) + XCTAssertTrue( + try manifest.isTargetDependencyEnabled( + target: "Foo", + trait3GuardedTargetDependency, + enabledTraits: ["Trait1", "Trait2", "Trait3"] + ) + ) // Test if a trait-guarded dependency is enabled when there are no enabled traits passsed. - XCTAssertFalse(try manifest.isTargetDependencyEnabled( - target: "Foo", - trait3GuardedTargetDependency, - enabledTraits: ["default"] - )) + XCTAssertFalse( + try manifest.isTargetDependencyEnabled( + target: "Foo", + trait3GuardedTargetDependency, + enabledTraits: ["default"] + ) + ) // Test if a target dependency guarded by default traits is enabled when passed no explicitly // enabled traits; should be true. - XCTAssertTrue(try manifest.isTargetDependencyEnabled( - target: "Foo", - defaultTraitGuardedTargetDependency, - enabledTraits: ["default"] - )) + XCTAssertTrue( + try manifest.isTargetDependencyEnabled( + target: "Foo", + defaultTraitGuardedTargetDependency, + enabledTraits: ["default"] + ) + ) // Test if a target dependency guarded by default traits is enabled when passed an empty set // of enabled traits, overriding the default traits; should be false. - XCTAssertFalse(try manifest.isTargetDependencyEnabled( - target: "Foo", - defaultTraitGuardedTargetDependency, - enabledTraits: [] - )) + XCTAssertFalse( + try manifest.isTargetDependencyEnabled( + target: "Foo", + defaultTraitGuardedTargetDependency, + enabledTraits: [] + ) + ) // Test if a target dependency that isn't guarded by traits wherein it uses a product // from the same package as another target dependency that is guarded by traits; should be true. - XCTAssertTrue(try manifest.isTargetDependencyEnabled( - target: "Foo", - enabledTargetDependencyWithSamePackage, - enabledTraits: [] - )) + XCTAssertTrue( + try manifest.isTargetDependencyEnabled( + target: "Foo", + enabledTargetDependencyWithSamePackage, + enabledTraits: [] + ) + ) // Test variations of traits that enable a target dependency that is unguarded by many traits. - XCTAssertFalse(try manifest.isTargetDependencyEnabled( - target: "Foo", - manyTraitsEnableTargetDependency, - enabledTraits: [] - )) - XCTAssertTrue(try manifest.isTargetDependencyEnabled( - target: "Foo", - manyTraitsEnableTargetDependency, - enabledTraits: ["Space"] - )) - XCTAssertTrue(try manifest.isTargetDependencyEnabled( - target: "Foo", - manyTraitsEnableTargetDependency, - enabledTraits: ["Music"] - )) - XCTAssertTrue(try manifest.isTargetDependencyEnabled( - target: "Foo", - manyTraitsEnableTargetDependency, - enabledTraits: ["Music", "Space"] - )) - XCTAssertTrue(try manifest.isTargetDependencyEnabled( - target: "Foo", - manyTraitsEnableTargetDependency, - enabledTraits: ["Trait3", "Music", "Space", "Trait1", "Trait2"] - )) + XCTAssertFalse( + try manifest.isTargetDependencyEnabled( + target: "Foo", + manyTraitsEnableTargetDependency, + enabledTraits: [] + ) + ) + XCTAssertTrue( + try manifest.isTargetDependencyEnabled( + target: "Foo", + manyTraitsEnableTargetDependency, + enabledTraits: ["Space"] + ) + ) + XCTAssertTrue( + try manifest.isTargetDependencyEnabled( + target: "Foo", + manyTraitsEnableTargetDependency, + enabledTraits: ["Music"] + ) + ) + XCTAssertTrue( + try manifest.isTargetDependencyEnabled( + target: "Foo", + manyTraitsEnableTargetDependency, + enabledTraits: ["Music", "Space"] + ) + ) + XCTAssertTrue( + try manifest.isTargetDependencyEnabled( + target: "Foo", + manyTraitsEnableTargetDependency, + enabledTraits: ["Trait3", "Music", "Space", "Trait1", "Trait2"] + ) + ) } } @@ -852,7 +911,7 @@ class ManifestTests: XCTestCase { ] let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ] let unguardedTargetDependency: TargetDescription.Dependency = .product( @@ -889,7 +948,7 @@ class ManifestTests: XCTestCase { unguardedTargetDependency, trait3GuardedTargetDependency, defaultTraitGuardedTargetDependency, - manyTraitsGuardingTargetDependency + manyTraitsGuardingTargetDependency, ] ) @@ -965,7 +1024,7 @@ class ManifestTests: XCTestCase { name: "Bar", package: "Bar", condition: .init(traits: ["Trait1"]) - ), + ) ] ), TargetDescription(name: "Bar", dependencies: ["Baz"]), @@ -1015,7 +1074,7 @@ class ManifestTests: XCTestCase { name: "Bar", package: "Bar", condition: .init(traits: ["Trait1"]) - ), + ) ] ), TargetDescription( @@ -1025,14 +1084,14 @@ class ManifestTests: XCTestCase { name: "Baz", package: "Baz", condition: .init(traits: ["Trait2"]) - ), + ) ] ), TargetDescription( name: "Baz", dependencies: [ "MyPlugin", - "Bar", // Bar as a dependency is not trait-guarded here + "Bar", // Bar as a dependency is not trait-guarded here ] ), TargetDescription(name: "FooBar", dependencies: []), @@ -1107,7 +1166,7 @@ class ManifestTests: XCTestCase { name: "Bar", package: "Bar", condition: .init(traits: ["Trait1"]) - ), + ) ] ), TargetDescription(name: "Bar", dependencies: ["Baz"]), @@ -1146,7 +1205,7 @@ class ManifestTests: XCTestCase { func testTargetDescriptionDependencyName_ForProduct() throws { let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ] let targets = try [ @@ -1156,9 +1215,9 @@ class ManifestTests: XCTestCase { .product( name: "Bar", package: "Blah" - ), + ) ] - ), + ) ] do { @@ -1182,7 +1241,7 @@ class ManifestTests: XCTestCase { func testTargetDescriptionDependencyName_ForTarget() throws { let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ] let targets = try [ @@ -1191,9 +1250,9 @@ class ManifestTests: XCTestCase { dependencies: [ .target( name: "Baz" - ), + ) ] - ), + ) ] do { @@ -1217,16 +1276,16 @@ class ManifestTests: XCTestCase { func testTargetDescriptionDependencyName_ForByName() throws { let products = try [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ] let targets = try [ TargetDescription( name: "Foo", dependencies: [ - "Boo", + "Boo" ] - ), + ) ] do { diff --git a/Tests/PackageModelTests/MinimumDeploymentTargetTests.swift b/Tests/PackageModelTests/MinimumDeploymentTargetTests.swift index a5ca87fabee..b1045e5048f 100644 --- a/Tests/PackageModelTests/MinimumDeploymentTargetTests.swift +++ b/Tests/PackageModelTests/MinimumDeploymentTargetTests.swift @@ -18,8 +18,8 @@ import struct Basics.AsyncProcessResult final class MinimumDeploymentTargetTests: XCTestCase { func testDoesNotAssertWithNoOutput() throws { #if !os(macOS) - // these tests eventually call `xcrun`. - try XCTSkipIf(true, "test is only supported on macOS") + // these tests eventually call `xcrun`. + try XCTSkipIf(true, "test is only supported on macOS") #endif let result = AsyncProcessResult( arguments: [], @@ -34,8 +34,8 @@ final class MinimumDeploymentTargetTests: XCTestCase { func testThrowsWithNonPathOutput() throws { #if !os(macOS) - // these tests eventually call `xcrun`. - try XCTSkipIf(true, "test is only supported on macOS") + // these tests eventually call `xcrun`. + try XCTSkipIf(true, "test is only supported on macOS") #endif let result = AsyncProcessResult( arguments: [], @@ -45,16 +45,18 @@ final class MinimumDeploymentTargetTests: XCTestCase { stderrOutput: "".asResult ) - XCTAssertThrowsError(try MinimumDeploymentTarget.computeXCTestMinimumDeploymentTarget( - with: result, - platform: .macOS - )) + XCTAssertThrowsError( + try MinimumDeploymentTarget.computeXCTestMinimumDeploymentTarget( + with: result, + platform: .macOS + ) + ) } func testThrowsWithErrorForOutput() throws { #if !os(macOS) - // these tests eventually call `xcrun`. - try XCTSkipIf(true, "test is only supported on macOS") + // these tests eventually call `xcrun`. + try XCTSkipIf(true, "test is only supported on macOS") #endif let result = AsyncProcessResult( arguments: [], @@ -64,10 +66,12 @@ final class MinimumDeploymentTargetTests: XCTestCase { stderrOutput: "".asResult ) - XCTAssertThrowsError(try MinimumDeploymentTarget.computeXCTestMinimumDeploymentTarget( - with: result, - platform: .macOS - )) + XCTAssertThrowsError( + try MinimumDeploymentTarget.computeXCTestMinimumDeploymentTarget( + with: result, + platform: .macOS + ) + ) } } diff --git a/Tests/PackageModelTests/PackageModelTests.swift b/Tests/PackageModelTests/PackageModelTests.swift index 9d230b286d5..ef995dc40e4 100644 --- a/Tests/PackageModelTests/PackageModelTests.swift +++ b/Tests/PackageModelTests/PackageModelTests.swift @@ -12,8 +12,7 @@ import Basics -@_spi(SwiftPMInternal) -@testable import PackageModel +@_spi(SwiftPMInternal) @testable import PackageModel import func TSCBasic.withTemporaryFile import XCTest @@ -104,9 +103,9 @@ final class PackageModelTests: XCTestCase { func testWindowsLibrarianSelection() throws { #if os(Windows) - let suffix = ".exe" + let suffix = ".exe" #else - let suffix = "" + let suffix = "" #endif let triple = try Triple("x86_64-unknown-windows-msvc") @@ -125,13 +124,17 @@ final class PackageModelTests: XCTestCase { try fs.writeFileContents(not, bytes: ByteString(contents)) #if !os(Windows) - try fs.chmod(.executable, path: lld, options: []) - try fs.chmod(.executable, path: not, options: []) + try fs.chmod(.executable, path: lld, options: []) + try fs.chmod(.executable, path: not, options: []) #endif try XCTAssertEqual( UserToolchain.determineLibrarian( - triple: triple, binDirectories: [bin], useXcrun: false, environment: [:], searchPaths: [], + triple: triple, + binDirectories: [bin], + useXcrun: false, + environment: [:], + searchPaths: [], extraSwiftFlags: ["-Xswiftc", "-use-ld=lld"], fileSystem: fs ), @@ -140,7 +143,11 @@ final class PackageModelTests: XCTestCase { try XCTAssertEqual( UserToolchain.determineLibrarian( - triple: triple, binDirectories: [bin], useXcrun: false, environment: [:], searchPaths: [], + triple: triple, + binDirectories: [bin], + useXcrun: false, + environment: [:], + searchPaths: [], extraSwiftFlags: ["-Xswiftc", "-use-ld=not-link"], fileSystem: fs ), @@ -149,7 +156,11 @@ final class PackageModelTests: XCTestCase { try XCTAssertThrowsError( UserToolchain.determineLibrarian( - triple: triple, binDirectories: [bin], useXcrun: false, environment: [:], searchPaths: [], + triple: triple, + binDirectories: [bin], + useXcrun: false, + environment: [:], + searchPaths: [], extraSwiftFlags: [], fileSystem: fs ) @@ -160,43 +171,43 @@ final class PackageModelTests: XCTestCase { func testDetermineSwiftCompilers() throws { let fs = localFileSystem - try withTemporaryDirectory(removeTreeOnDeinit: true) { tmp in - // When swiftc is not in the toolchain bin directory, UserToolchain - // should find it in the system PATH search paths in the order they - // are specified. - let toolchainPath = tmp.appending("swift.xctoolchain") - let toolchainBinDir = toolchainPath.appending(components: "usr", "bin") - // Create the toolchain bin directory, but don't put swiftc in it. - try fs.createDirectory(toolchainBinDir, recursive: true) - - // Create a directory with two swiftc binaries in it. - let binDirs = ["bin1", "bin2"].map { tmp.appending($0) } - #if os(Windows) + try withTemporaryDirectory(removeTreeOnDeinit: true) { tmp in + // When swiftc is not in the toolchain bin directory, UserToolchain + // should find it in the system PATH search paths in the order they + // are specified. + let toolchainPath = tmp.appending("swift.xctoolchain") + let toolchainBinDir = toolchainPath.appending(components: "usr", "bin") + // Create the toolchain bin directory, but don't put swiftc in it. + try fs.createDirectory(toolchainBinDir, recursive: true) + + // Create a directory with two swiftc binaries in it. + let binDirs = ["bin1", "bin2"].map { tmp.appending($0) } + #if os(Windows) let exeSuffix = ".exe" - #else + #else let exeSuffix = "" - #endif - let expectedExecuable = "swiftc\(exeSuffix)" // Files that end with .exe are considered executable on Windows. - for binDir in binDirs { - try fs.createDirectory(binDir) - let binFile = binDir.appending(expectedExecuable) - try fs.writeFileContents(binFile, bytes: ByteString(Self.tinyPEBytes)) - XCTAssertTrue(fs.exists(binFile), "File '\(binFile)' does not exist when it should") - #if !os(Windows) + #endif + let expectedExecuable = "swiftc\(exeSuffix)" // Files that end with .exe are considered executable on Windows. + for binDir in binDirs { + try fs.createDirectory(binDir) + let binFile = binDir.appending(expectedExecuable) + try fs.writeFileContents(binFile, bytes: ByteString(Self.tinyPEBytes)) + XCTAssertTrue(fs.exists(binFile), "File '\(binFile)' does not exist when it should") + #if !os(Windows) try fs.chmod(.executable, path: binFile, options: []) - #endif - } - - let compilers = try UserToolchain.determineSwiftCompilers( - binDirectories: [toolchainBinDir], - useXcrun: false, - environment: [:], - searchPaths: binDirs, - fileSystem: fs - ) - - // The first swiftc in the search paths should be chosen. - XCTAssertEqual(compilers.compile, binDirs.first?.appending(expectedExecuable)) + #endif } + + let compilers = try UserToolchain.determineSwiftCompilers( + binDirectories: [toolchainBinDir], + useXcrun: false, + environment: [:], + searchPaths: binDirs, + fileSystem: fs + ) + + // The first swiftc in the search paths should be chosen. + XCTAssertEqual(compilers.compile, binDirs.first?.appending(expectedExecuable)) + } } } diff --git a/Tests/PackageModelTests/SnippetTests.swift b/Tests/PackageModelTests/SnippetTests.swift index fa9af97da89..e42ea9117d4 100644 --- a/Tests/PackageModelTests/SnippetTests.swift +++ b/Tests/PackageModelTests/SnippetTests.swift @@ -42,21 +42,21 @@ struct SnippetTests { func testBasic() async throws { let explanation = "This snippet does a foo. Try it when XYZ." let presentationCode = """ - import Module + import Module - func foo(x: X) {} - """ + func foo(x: X) {} + """ let source = """ - //! \(explanation) + //! \(explanation) - \(presentationCode) + \(presentationCode) - // MARK: HIDE + // MARK: HIDE - print(foo(x: x())) - """ + print(foo(x: x())) + """ let snippet = Snippet(parsing: source, path: fakeSourceFilePath) @@ -76,34 +76,34 @@ struct SnippetTests { let presentationCode = """ - import Module + import Module - func foo(x: X) {} + func foo(x: X) {} - """ + """ let source = """ - //! - //! \(explanation) - //! + //! + //! \(explanation) + //! - \(presentationCode) + \(presentationCode) - // MARK: HIDE + // MARK: HIDE - print(foo(x: x())) - """ + print(foo(x: x())) + """ let expectedPresentationCode = """ - import Module + import Module - func foo(x: X) {} - """ + func foo(x: X) {} + """ let snippet = Snippet(parsing: source, path: fakeSourceFilePath) #expect(explanation == snippet.explanation) @@ -114,28 +114,28 @@ struct SnippetTests { /// works as intended. func testMarkHideShowToggle() async throws { let source = """ - shown1 + shown1 - // mark: hide - hidden1 + // mark: hide + hidden1 - // mark: show - shown2 + // mark: show + shown2 - // mark: hide - hidden2 + // mark: hide + hidden2 - // mark: show - shown3 - """ + // mark: show + shown3 + """ let expectedPresentationCode = """ - shown1 + shown1 + + shown2 - shown2 - - shown3 - """ + shown3 + """ let snippet = Snippet(parsing: source, path: fakeSourceFilePath) #expect(!snippet.presentationCode.contains("hidden")) @@ -148,21 +148,21 @@ struct SnippetTests { @Test func testRemoveExtraIndentation() async throws { let source = """ - // mark: hide - struct Outer { - struct Inner { - // mark: show - struct InnerInner { - } // mark: hide - } - } - """ + struct Outer { + struct Inner { + // mark: show + struct InnerInner { + } + // mark: hide + } + } + """ let expectedPresentationCode = """ - struct InnerInner { - } - """ + struct InnerInner { + } + """ let snippet = Snippet(parsing: source, path: fakeSourceFilePath) #expect(expectedPresentationCode == snippet.presentationCode) } diff --git a/Tests/PackageModelTests/SwiftLanguageVersionTests.swift b/Tests/PackageModelTests/SwiftLanguageVersionTests.swift index d0aa8ea7d51..4712bc0dce0 100644 --- a/Tests/PackageModelTests/SwiftLanguageVersionTests.swift +++ b/Tests/PackageModelTests/SwiftLanguageVersionTests.swift @@ -19,11 +19,11 @@ class SwiftLanguageVersionTests: XCTestCase { func testBasics() throws { let validVersions = [ - "4" : "4", - "4.0" : "4.0", - "4.2" : "4.2", - "1.0.0" : "1.0.0", - "3.1.0" : "3.1.0", + "4": "4", + "4.0": "4.0", + "4.2": "4.2", + "1.0.0": "1.0.0", + "3.1.0": "3.1.0", ] for (version, expected) in validVersions { diff --git a/Tests/PackageModelTests/SwiftSDKBundleTests.swift b/Tests/PackageModelTests/SwiftSDKBundleTests.swift index 8262336c8c3..230b15a9947 100644 --- a/Tests/PackageModelTests/SwiftSDKBundleTests.swift +++ b/Tests/PackageModelTests/SwiftSDKBundleTests.swift @@ -11,8 +11,7 @@ //===----------------------------------------------------------------------===// import Basics -@_spi(SwiftPMInternal) -@testable import PackageModel +@_spi(SwiftPMInternal) @testable import PackageModel import _InternalTestSupport import XCTest @@ -30,10 +29,11 @@ private func generateBundleFiles(bundle: MockBundle) throws -> [(String, ByteStr return try [ ( "\(bundle.path)/info.json", - ByteString(json: """ - { - "artifacts" : { - \(bundle.artifacts.map { + ByteString( + json: """ + { + "artifacts" : { + \(bundle.artifacts.map { let path = if let metadataPath = $0.metadataPath { metadataPath.pathString } else { @@ -54,41 +54,48 @@ private func generateBundleFiles(bundle: MockBundle) throws -> [(String, ByteStr """ }.joined(separator: ",\n") ) - }, - "schemaVersion" : "1.0" - } - """) - ), - - ] + bundle.artifacts.map { - let path = if let metadataPath = $0.metadataPath { - "\(bundle.path)/\(metadataPath.pathString)" - } else { - "\(bundle.path)/\($0.id)/\(targetTriple.triple)/swift-sdk.json" - } - - return ( - path, - ByteString(json: try generateSwiftSDKMetadata(jsonEncoder, createToolset: $0.toolsetRootPath != nil)) + }, + "schemaVersion" : "1.0" + } + """ + ) ) - } + bundle.artifacts.compactMap { artifact in - let toolsetPath = if artifact.metadataPath != nil { - "\(bundle.path)/toolset.json" - } else { - "\(bundle.path)/\(artifact.id)/\(targetTriple.triple)/toolset.json" - } - return artifact.toolsetRootPath.map { path in - ( - "\(toolsetPath)", - ByteString(json: """ - { - "schemaVersion": "1.0", - "rootPath": "\(path)" + + ] + + bundle.artifacts.map { + let path = + if let metadataPath = $0.metadataPath { + "\(bundle.path)/\(metadataPath.pathString)" + } else { + "\(bundle.path)/\($0.id)/\(targetTriple.triple)/swift-sdk.json" } - """) + + return ( + path, + ByteString(json: try generateSwiftSDKMetadata(jsonEncoder, createToolset: $0.toolsetRootPath != nil)) ) } - } + + bundle.artifacts.compactMap { artifact in + let toolsetPath = + if artifact.metadataPath != nil { + "\(bundle.path)/toolset.json" + } else { + "\(bundle.path)/\(artifact.id)/\(targetTriple.triple)/toolset.json" + } + return artifact.toolsetRootPath.map { path in + ( + "\(toolsetPath)", + ByteString( + json: """ + { + "schemaVersion": "1.0", + "rootPath": "\(path)" + } + """ + ) + ) + } + } } private func generateSwiftSDKMetadata(_ encoder: JSONEncoder, createToolset: Bool) throws -> SerializedJSON { @@ -157,7 +164,7 @@ private let fixtureSDKsPath = try! AbsolutePath(validating: #file) final class SwiftSDKBundleTests: XCTestCase { func testInstallRemote() async throws { #if canImport(Darwin) && !os(macOS) - try XCTSkipIf(true, "skipping test because process launching is not available") + try XCTSkipIf(true, "skipping test because process launching is not available") #endif let system = ObservabilitySystem.makeForTesting() @@ -198,17 +205,20 @@ final class SwiftSDKBundleTests: XCTestCase { } let bundleURL = URL(string: bundleURLString)! - XCTAssertEqual(output, [ - .downloadStarted(bundleURL), - .downloadFinishedSuccessfully(bundleURL), - .verifyingChecksum, - .checksumValid, - .unpackingArchive(bundlePathOrURL: bundleURLString), - .installationSuccessful( - bundlePathOrURL: bundleURLString, - bundleName: "test-sdk.artifactbundle" - ), - ]) + XCTAssertEqual( + output, + [ + .downloadStarted(bundleURL), + .downloadFinishedSuccessfully(bundleURL), + .verifyingChecksum, + .checksumValid, + .unpackingArchive(bundlePathOrURL: bundleURLString), + .installationSuccessful( + bundlePathOrURL: bundleURLString, + bundleName: "test-sdk.artifactbundle" + ), + ] + ) }.value } } @@ -219,7 +229,7 @@ final class SwiftSDKBundleTests: XCTestCase { let (fileSystem, bundles, swiftSDKsDirectory) = try generateTestFileSystem( bundleArtifacts: [ .init(id: testArtifactID, supportedTriples: [arm64Triple]), - .init(id: testArtifactID, supportedTriples: [arm64Triple]) + .init(id: testArtifactID, supportedTriples: [arm64Triple]), ] ) @@ -282,8 +292,8 @@ final class SwiftSDKBundleTests: XCTestCase { do { try await store.install(bundlePathOrURL: bundles[1].path, archiver) - XCTFail("Function expected to throw") - } catch { + XCTFail("Function expected to throw") + } catch { guard let error = error as? SwiftSDKError else { XCTFail("Unexpected error type") return @@ -299,13 +309,16 @@ final class SwiftSDKBundleTests: XCTestCase { } } - XCTAssertEqual(output, [ - .installationSuccessful( - bundlePathOrURL: bundles[0].path, - bundleName: AbsolutePath(bundles[0].path).components.last! - ), - .unpackingArchive(bundlePathOrURL: invalidPath), - ]) + XCTAssertEqual( + output, + [ + .installationSuccessful( + bundlePathOrURL: bundles[0].path, + bundleName: AbsolutePath(bundles[0].path).components.last! + ), + .unpackingArchive(bundlePathOrURL: invalidPath), + ] + ) } func testList() async throws { @@ -338,23 +351,26 @@ final class SwiftSDKBundleTests: XCTestCase { XCTAssertEqual(validBundles.count, bundles.count) XCTAssertEqual(validBundles.sortedArtifactIDs, ["\(testArtifactID)1", "\(testArtifactID)2"]) - XCTAssertEqual(output, [ - .installationSuccessful( - bundlePathOrURL: bundles[0].path, - bundleName: AbsolutePath(bundles[0].path).components.last! - ), - .installationSuccessful( - bundlePathOrURL: bundles[1].path, - bundleName: AbsolutePath(bundles[1].path).components.last! - ), - ]) + XCTAssertEqual( + output, + [ + .installationSuccessful( + bundlePathOrURL: bundles[0].path, + bundleName: AbsolutePath(bundles[0].path).components.last! + ), + .installationSuccessful( + bundlePathOrURL: bundles[1].path, + bundleName: AbsolutePath(bundles[1].path).components.last! + ), + ] + ) } func testBundleSelection() async throws { let (fileSystem, bundles, swiftSDKsDirectory) = try generateTestFileSystem( bundleArtifacts: [ .init(id: "\(testArtifactID)1", supportedTriples: [arm64Triple]), - .init(id: "\(testArtifactID)2", supportedTriples: [i686Triple]) + .init(id: "\(testArtifactID)2", supportedTriples: [i686Triple]), ] ) let system = ObservabilitySystem.makeForTesting() @@ -381,16 +397,19 @@ final class SwiftSDKBundleTests: XCTestCase { ) XCTAssertEqual(sdk.targetTriple, targetTriple) - XCTAssertEqual(output, [ - .installationSuccessful( - bundlePathOrURL: bundles[0].path, - bundleName: AbsolutePath(bundles[0].path).components.last! - ), - .installationSuccessful( - bundlePathOrURL: bundles[1].path, - bundleName: AbsolutePath(bundles[1].path).components.last! - ), - ]) + XCTAssertEqual( + output, + [ + .installationSuccessful( + bundlePathOrURL: bundles[0].path, + bundleName: AbsolutePath(bundles[0].path).components.last! + ), + .installationSuccessful( + bundlePathOrURL: bundles[1].path, + bundleName: AbsolutePath(bundles[1].path).components.last! + ), + ] + ) } func testTargetSDKDerivation() async throws { @@ -413,7 +432,7 @@ final class SwiftSDKBundleTests: XCTestCase { observabilityScope: system.topScope, outputHandler: { _ in } ) - + for bundle in bundles { try await store.install(bundlePathOrURL: bundle.path, archiver) } @@ -520,7 +539,7 @@ final class SwiftSDKBundleTests: XCTestCase { ) let system = ObservabilitySystem.makeForTesting() let archiver = MockArchiver() - + var output = [SwiftSDKBundleStore.Output]() let store = SwiftSDKBundleStore( swiftSDKsDirectory: swiftSDKsDirectory, @@ -540,23 +559,26 @@ final class SwiftSDKBundleTests: XCTestCase { XCTAssertEqual(validBundles.sortedArtifactIDs, ["\(testArtifactID)1", "\(testArtifactID)2"]) XCTAssertEqual(output.count, 2) - XCTAssertEqual(output, [ - .installationSuccessful( - bundlePathOrURL: bundles[0].path, - bundleName: AbsolutePath(bundles[0].path).components.last! - ), - .installationSuccessful( - bundlePathOrURL: bundles[1].path, - bundleName: AbsolutePath(bundles[1].path).components.last! - ), - ]) + XCTAssertEqual( + output, + [ + .installationSuccessful( + bundlePathOrURL: bundles[0].path, + bundleName: AbsolutePath(bundles[0].path).components.last! + ), + .installationSuccessful( + bundlePathOrURL: bundles[1].path, + bundleName: AbsolutePath(bundles[1].path).components.last! + ), + ] + ) } func testConfigureSDKRootPath() async throws { func createConfigurationStore() async throws -> (SwiftSDKConfigurationStore, FileSystem) { let (fileSystem, bundles, swiftSDKsDirectory) = try generateTestFileSystem( bundleArtifacts: [ - .init(id: testArtifactID, supportedTriples: [arm64Triple, i686Triple]), + .init(id: testArtifactID, supportedTriples: [arm64Triple, i686Triple]) ] ) let system = ObservabilitySystem.makeForTesting() @@ -584,12 +606,15 @@ final class SwiftSDKBundleTests: XCTestCase { ) XCTAssertEqual(sdk.targetTriple, targetTriple) - XCTAssertEqual(output, [ - .installationSuccessful( - bundlePathOrURL: bundles[0].path, - bundleName: AbsolutePath(bundles[0].path).components.last! - ) - ]) + XCTAssertEqual( + output, + [ + .installationSuccessful( + bundlePathOrURL: bundles[0].path, + bundleName: AbsolutePath(bundles[0].path).components.last! + ) + ] + ) let config = try SwiftSDKConfigurationStore( hostTimeTriple: hostTriple, @@ -615,9 +640,9 @@ final class SwiftSDKBundleTests: XCTestCase { let targetTripleConfigPath = AbsolutePath("/sdks/configuration/\(testArtifactID)_\(targetTriple.tripleString).json") #if os(Windows) - let sdkRootPath = "C:\\some\\sdk\\root\\path" + let sdkRootPath = "C:\\some\\sdk\\root\\path" #else - let sdkRootPath = "/some/sdk/root/path" + let sdkRootPath = "/some/sdk/root/path" #endif do { diff --git a/Tests/PackageModelTests/SwiftSDKTests.swift b/Tests/PackageModelTests/SwiftSDKTests.swift index 999622ee993..162370482d3 100644 --- a/Tests/PackageModelTests/SwiftSDKTests.swift +++ b/Tests/PackageModelTests/SwiftSDKTests.swift @@ -12,8 +12,7 @@ @testable import Basics -@_spi(SwiftPMInternal) -@testable import PackageModel +@_spi(SwiftPMInternal) @testable import PackageModel @testable import SPMBuildCore import XCTest @@ -141,7 +140,6 @@ private let invalidToolsetDestinationV3 = ( """# as SerializedJSON ) - private let wasiWithoutToolsetsSwiftSDKv4 = ( path: bundleRootPath.appending(component: "wasiSwiftSDKv4.json"), json: #""" @@ -246,9 +244,11 @@ private let invalidToolsetSwiftSDKv4 = ( """# as SerializedJSON ) -private let usrBinTools = Dictionary(uniqueKeysWithValues: Toolset.KnownTool.allCases.map { - ($0, "/usr/bin/\($0.rawValue)") -}) +private let usrBinTools = Dictionary( + uniqueKeysWithValues: Toolset.KnownTool.allCases.map { + ($0, "/usr/bin/\($0.rawValue)") + } +) private let otherToolsNoRoot = ( path: try! AbsolutePath(validating: "/tools/otherToolsNoRoot.json"), @@ -435,7 +435,7 @@ final class SwiftSDKTests: XCTestCase { pathsConfiguration: .init( sdkRootPath: sdkRootAbsolutePath ) - ), + ) ] ) @@ -466,12 +466,14 @@ final class SwiftSDKTests: XCTestCase { XCTAssertEqual(toolsetRootDestinationV3Decoded, [parsedToolsetRootDestination]) - XCTAssertThrowsError(try SwiftSDK.decode( - fromFile: missingToolsetDestinationV3.path, - hostToolchainBinDir: toolchainBinAbsolutePath, - fileSystem: fs, - observabilityScope: observability - )) { + XCTAssertThrowsError( + try SwiftSDK.decode( + fromFile: missingToolsetDestinationV3.path, + hostToolchainBinDir: toolchainBinAbsolutePath, + fileSystem: fs, + observabilityScope: observability + ) + ) { let toolsetDefinition: AbsolutePath = "/tools/asdf.json" XCTAssertEqual( $0 as? StringError, @@ -483,19 +485,23 @@ final class SwiftSDKTests: XCTestCase { ) ) } - XCTAssertThrowsError(try SwiftSDK.decode( - fromFile: invalidVersionDestinationV3.path, - hostToolchainBinDir: bundleRootPath.appending(toolchainBinDir), - fileSystem: fs, - observabilityScope: observability - )) + XCTAssertThrowsError( + try SwiftSDK.decode( + fromFile: invalidVersionDestinationV3.path, + hostToolchainBinDir: bundleRootPath.appending(toolchainBinDir), + fileSystem: fs, + observabilityScope: observability + ) + ) - XCTAssertThrowsError(try SwiftSDK.decode( - fromFile: invalidToolsetDestinationV3.path, - hostToolchainBinDir: bundleRootPath.appending(toolchainBinDir), - fileSystem: fs, - observabilityScope: observability - )) { + XCTAssertThrowsError( + try SwiftSDK.decode( + fromFile: invalidToolsetDestinationV3.path, + hostToolchainBinDir: bundleRootPath.appending(toolchainBinDir), + fileSystem: fs, + observabilityScope: observability + ) + ) { let toolsetDefinition: AbsolutePath = "/tools/invalidToolset.json" XCTAssertTrue( ($0 as? StringError)?.description @@ -530,12 +536,14 @@ final class SwiftSDKTests: XCTestCase { XCTAssertEqual(androidWithoutSDKRootPathSwiftSDKv4Decoded, [parsedToolsetNoSDKRootPathDestination]) - XCTAssertThrowsError(try SwiftSDK.decode( - fromFile: missingToolsetSwiftSDKv4.path, - hostToolchainBinDir: toolchainBinAbsolutePath, - fileSystem: fs, - observabilityScope: observability - )) { + XCTAssertThrowsError( + try SwiftSDK.decode( + fromFile: missingToolsetSwiftSDKv4.path, + hostToolchainBinDir: toolchainBinAbsolutePath, + fileSystem: fs, + observabilityScope: observability + ) + ) { let toolsetDefinition: AbsolutePath = "/tools/asdf.json" XCTAssertEqual( $0 as? StringError, @@ -547,19 +555,23 @@ final class SwiftSDKTests: XCTestCase { ) ) } - XCTAssertThrowsError(try SwiftSDK.decode( - fromFile: invalidVersionSwiftSDKv4.path, - hostToolchainBinDir: toolchainBinAbsolutePath, - fileSystem: fs, - observabilityScope: observability - )) + XCTAssertThrowsError( + try SwiftSDK.decode( + fromFile: invalidVersionSwiftSDKv4.path, + hostToolchainBinDir: toolchainBinAbsolutePath, + fileSystem: fs, + observabilityScope: observability + ) + ) - XCTAssertThrowsError(try SwiftSDK.decode( - fromFile: invalidToolsetSwiftSDKv4.path, - hostToolchainBinDir: toolchainBinAbsolutePath, - fileSystem: fs, - observabilityScope: observability - )) { + XCTAssertThrowsError( + try SwiftSDK.decode( + fromFile: invalidToolsetSwiftSDKv4.path, + hostToolchainBinDir: toolchainBinAbsolutePath, + fileSystem: fs, + observabilityScope: observability + ) + ) { let toolsetDefinition: AbsolutePath = "/tools/invalidToolset.json" XCTAssertTrue( ($0 as? StringError)?.description @@ -597,7 +609,7 @@ final class SwiftSDKTests: XCTestCase { supportedTriples: [hostTriple] ), swiftSDKs: [parsedDestinationV2GNU] - ), + ) ], "id2": [ .init( @@ -606,7 +618,7 @@ final class SwiftSDKTests: XCTestCase { supportedTriples: [] ), swiftSDKs: [parsedDestinationV2GNU] - ), + ) ], "id3": [ .init( @@ -615,7 +627,7 @@ final class SwiftSDKTests: XCTestCase { supportedTriples: [hostTriple] ), swiftSDKs: [parsedDestinationV2Musl] - ), + ) ], "id4": [ .init( @@ -624,7 +636,7 @@ final class SwiftSDKTests: XCTestCase { supportedTriples: [olderHostTriple] ), swiftSDKs: [parsedDestinationForOlderHost] - ), + ) ], "id5": [ .init( @@ -633,10 +645,10 @@ final class SwiftSDKTests: XCTestCase { supportedTriples: nil ), swiftSDKs: [parsedDestinationV2GNU] - ), + ) ], ] - ), + ) ] let system = ObservabilitySystem.makeForTesting() @@ -710,24 +722,26 @@ final class SwiftSDKTests: XCTestCase { let hostSDK = try SwiftSDK.hostSwiftSDK("/prefix/bin") #if os(macOS) - let iOSPlatform = try AbsolutePath(validating: "/usr/share/iPhoneOS.platform") - let iOSRoot = try AbsolutePath(validating: "/usr/share/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk") - let iOSTriple = try Triple("arm64-apple-ios") - let iOS = try XCTUnwrap(SwiftSDK.defaultSwiftSDK( - for: iOSTriple, - hostSDK: hostSDK, - environment: [ - "SWIFTPM_PLATFORM_PATH_iphoneos": iOSPlatform.pathString, - "SWIFTPM_SDKROOT_iphoneos": iOSRoot.pathString, - ] - )) - XCTAssertEqual(iOS.toolset.rootPaths, hostSDK.toolset.rootPaths) + let iOSPlatform = try AbsolutePath(validating: "/usr/share/iPhoneOS.platform") + let iOSRoot = try AbsolutePath(validating: "/usr/share/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk") + let iOSTriple = try Triple("arm64-apple-ios") + let iOS = try XCTUnwrap( + SwiftSDK.defaultSwiftSDK( + for: iOSTriple, + hostSDK: hostSDK, + environment: [ + "SWIFTPM_PLATFORM_PATH_iphoneos": iOSPlatform.pathString, + "SWIFTPM_SDKROOT_iphoneos": iOSRoot.pathString, + ] + ) + ) + XCTAssertEqual(iOS.toolset.rootPaths, hostSDK.toolset.rootPaths) - XCTAssertEqual(iOS.pathsConfiguration.sdkRootPath, iOSRoot) + XCTAssertEqual(iOS.pathsConfiguration.sdkRootPath, iOSRoot) - let cFlags = iOS.toolset.knownTools[.cCompiler]?.extraCLIOptions ?? [] - XCTAssert(cFlags.contains(["-F", "\(iOSPlatform.pathString)/Developer/Library/Frameworks"])) - XCTAssertFalse(cFlags.contains { $0.lowercased().contains("macos") }, "Found macOS path in \(cFlags)") + let cFlags = iOS.toolset.knownTools[.cCompiler]?.extraCLIOptions ?? [] + XCTAssert(cFlags.contains(["-F", "\(iOSPlatform.pathString)/Developer/Library/Frameworks"])) + XCTAssertFalse(cFlags.contains { $0.lowercased().contains("macos") }, "Found macOS path in \(cFlags)") #endif } } diff --git a/Tests/PackageModelTests/ToolsVersionTests.swift b/Tests/PackageModelTests/ToolsVersionTests.swift index 488e74680b8..d733172b1f5 100644 --- a/Tests/PackageModelTests/ToolsVersionTests.swift +++ b/Tests/PackageModelTests/ToolsVersionTests.swift @@ -52,7 +52,7 @@ struct ToolsVersionTests { func basicsValidVersions( version: String, expected: String - ) async throws { + ) async throws { let toolsVersion = try #require( ToolsVersion(string: version), "Couldn't form a version with string: \(version)" @@ -95,7 +95,7 @@ struct ToolsVersionTests { func runtimeSubpath( version: String, expectedRuntimeSubpath: String, - ) async throws { + ) async throws { let version = try #require(ToolsVersion(string: version)) #expect(version.runtimeSubpath.pathString == expectedRuntimeSubpath) @@ -117,7 +117,7 @@ struct ToolsVersionTests { func swiftLangVersion( version: String, expectedSwiftLanguageVersion: String, - ) async throws { + ) async throws { let version = try #require(ToolsVersion(string: version)) #expect(version.swiftLanguageVersion.description == expectedSwiftLanguageVersion) } diff --git a/Tests/PackageModelTests/ToolsetTests.swift b/Tests/PackageModelTests/ToolsetTests.swift index d0568e4127a..d5ca1246c44 100644 --- a/Tests/PackageModelTests/ToolsetTests.swift +++ b/Tests/PackageModelTests/ToolsetTests.swift @@ -15,9 +15,11 @@ import _InternalTestSupport import XCTest -private let usrBinTools = Dictionary(uniqueKeysWithValues: Toolset.KnownTool.allCases.map { - ($0, try! AbsolutePath(validating: "/usr/bin/\($0.rawValue)")) -}) +private let usrBinTools = Dictionary( + uniqueKeysWithValues: Toolset.KnownTool.allCases.map { + ($0, try! AbsolutePath(validating: "/usr/bin/\($0.rawValue)")) + } +) private let cCompilerOptions = ["-fopenmp"] private let newCCompilerOptions = ["-pedantic"] diff --git a/Tests/PackageRegistryTests/PackageSigningEntityTOFUTests.swift b/Tests/PackageRegistryTests/PackageSigningEntityTOFUTests.swift index c1df6bb1fa4..d441511c082 100644 --- a/Tests/PackageRegistryTests/PackageSigningEntityTOFUTests.swift +++ b/Tests/PackageRegistryTests/PackageSigningEntityTOFUTests.swift @@ -137,14 +137,18 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [signingEntity: PackageSigner( - signingEntity: signingEntity, - origins: [.registry(registry.url)], - versions: [version] - )] - )] + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + signingEntity: PackageSigner( + signingEntity: signingEntity, + origins: [.registry(registry.url)], + versions: [version] + ) + ] + ) + ] ) let signingEntityCheckingMode = SigningEntityCheckingMode.strict @@ -181,16 +185,20 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [existingSigningEntity: PackageSigner( - signingEntity: existingSigningEntity, - origins: [.registry(registry.url)], - versions: [version] - )] - )] - ) - let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + existingSigningEntity: PackageSigner( + signingEntity: existingSigningEntity, + origins: [.registry(registry.url)], + versions: [version] + ) + ] + ) + ] + ) + let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change let tofu = PackageSigningEntityTOFU( signingEntityStorage: signingEntityStorage, @@ -241,16 +249,20 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [existingSigningEntity: PackageSigner( - signingEntity: existingSigningEntity, - origins: [.registry(registry.url)], - versions: [version] - )] - )] - ) - let signingEntityCheckingMode = SigningEntityCheckingMode.warn // intended for this test; don't change + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + existingSigningEntity: PackageSigner( + signingEntity: existingSigningEntity, + origins: [.registry(registry.url)], + versions: [version] + ) + ] + ) + ] + ) + let signingEntityCheckingMode = SigningEntityCheckingMode.warn // intended for this test; don't change let tofu = PackageSigningEntityTOFU( signingEntityStorage: signingEntityStorage, @@ -296,16 +308,20 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [existingSigningEntity: PackageSigner( - signingEntity: existingSigningEntity, - origins: [.registry(registry.url)], - versions: [version] - )] - )] - ) - let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + existingSigningEntity: PackageSigner( + signingEntity: existingSigningEntity, + origins: [.registry(registry.url)], + versions: [version] + ) + ] + ) + ] + ) + let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change let tofu = PackageSigningEntityTOFU( signingEntityStorage: signingEntityStorage, @@ -351,14 +367,18 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [signingEntity: PackageSigner( - signingEntity: signingEntity, - origins: [.registry(registry.url)], - versions: [existingVersion] - )] - )] + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + signingEntity: PackageSigner( + signingEntity: signingEntity, + origins: [.registry(registry.url)], + versions: [existingVersion] + ) + ] + ) + ] ) let signingEntityCheckingMode = SigningEntityCheckingMode.strict @@ -404,16 +424,20 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [existingSigningEntity: PackageSigner( - signingEntity: existingSigningEntity, - origins: [.registry(registry.url)], - versions: [existingVersion] - )] - )] - ) - let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + existingSigningEntity: PackageSigner( + signingEntity: existingSigningEntity, + origins: [.registry(registry.url)], + versions: [existingVersion] + ) + ] + ) + ] + ) + let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change let tofu = PackageSigningEntityTOFU( signingEntityStorage: signingEntityStorage, @@ -430,14 +454,16 @@ final class PackageSigningEntityTOFUTests: XCTestCase { signingEntity: signingEntity ) ) { error in - guard case RegistryError.signingEntityForPackageChanged( - _, - _, - _, - let latest, - let previous, - let previousVersion - ) = error else { + guard + case RegistryError.signingEntityForPackageChanged( + _, + _, + _, + let latest, + let previous, + let previousVersion + ) = error + else { return XCTFail("Expected RegistryError.signingEntityForPackageChanged, got '\(error)'") } XCTAssertEqual(latest, signingEntity) @@ -473,16 +499,20 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [existingSigningEntity: PackageSigner( - signingEntity: existingSigningEntity, - origins: [.registry(registry.url)], - versions: [existingVersion] - )] - )] - ) - let signingEntityCheckingMode = SigningEntityCheckingMode.warn // intended for this test; don't change + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + existingSigningEntity: PackageSigner( + signingEntity: existingSigningEntity, + origins: [.registry(registry.url)], + versions: [existingVersion] + ) + ] + ) + ] + ) + let signingEntityCheckingMode = SigningEntityCheckingMode.warn // intended for this test; don't change let tofu = PackageSigningEntityTOFU( signingEntityStorage: signingEntityStorage, @@ -529,14 +559,18 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [existingSigningEntity: PackageSigner( - signingEntity: existingSigningEntity, - origins: [.registry(registry.url)], - versions: existingVersions - )] - )] + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + existingSigningEntity: PackageSigner( + signingEntity: existingSigningEntity, + origins: [.registry(registry.url)], + versions: existingVersions + ) + ] + ) + ] ) let signingEntityCheckingMode = SigningEntityCheckingMode.strict @@ -577,16 +611,20 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [existingSigningEntity: PackageSigner( - signingEntity: existingSigningEntity, - origins: [.registry(registry.url)], - versions: existingVersions - )] - )] - ) - let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + existingSigningEntity: PackageSigner( + signingEntity: existingSigningEntity, + origins: [.registry(registry.url)], + versions: existingVersions + ) + ] + ) + ] + ) + let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change let tofu = PackageSigningEntityTOFU( signingEntityStorage: signingEntityStorage, @@ -604,14 +642,16 @@ final class PackageSigningEntityTOFUTests: XCTestCase { signingEntity: .none ) ) { error in - guard case RegistryError.signingEntityForPackageChanged( - _, - _, - _, - let latest, - let previous, - let previousVersion - ) = error else { + guard + case RegistryError.signingEntityForPackageChanged( + _, + _, + _, + let latest, + let previous, + let previousVersion + ) = error + else { return XCTFail("Expected RegistryError.signingEntityForPackageChanged, got '\(error)'") } XCTAssertNil(latest) @@ -641,16 +681,20 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [existingSigningEntity: PackageSigner( - signingEntity: existingSigningEntity, - origins: [.registry(registry.url)], - versions: existingVersions - )] - )] - ) - let signingEntityCheckingMode = SigningEntityCheckingMode.warn // intended for this test; don't change + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + existingSigningEntity: PackageSigner( + signingEntity: existingSigningEntity, + origins: [.registry(registry.url)], + versions: existingVersions + ) + ] + ) + ] + ) + let signingEntityCheckingMode = SigningEntityCheckingMode.warn // intended for this test; don't change let tofu = PackageSigningEntityTOFU( signingEntityStorage: signingEntityStorage, @@ -698,14 +742,18 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: .none, - signers: [existingSigningEntity: PackageSigner( - signingEntity: existingSigningEntity, - origins: [.registry(registry.url)], - versions: existingVersions - )] - )] + [ + package.underlying: PackageSigners( + expectedSigner: .none, + signers: [ + existingSigningEntity: PackageSigner( + signingEntity: existingSigningEntity, + origins: [.registry(registry.url)], + versions: existingVersions + ) + ] + ) + ] ) let signingEntityCheckingMode = SigningEntityCheckingMode.strict @@ -748,14 +796,18 @@ final class PackageSigningEntityTOFUTests: XCTestCase { let expectedFromVersion = Version("1.5.0") let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: (signingEntity: expectedSigningEntity, fromVersion: expectedFromVersion), - signers: [expectedSigningEntity: PackageSigner( - signingEntity: expectedSigningEntity, - origins: [.registry(registry.url)], - versions: [expectedFromVersion] - )] - )] + [ + package.underlying: PackageSigners( + expectedSigner: (signingEntity: expectedSigningEntity, fromVersion: expectedFromVersion), + signers: [ + expectedSigningEntity: PackageSigner( + signingEntity: expectedSigningEntity, + origins: [.registry(registry.url)], + versions: [expectedFromVersion] + ) + ] + ) + ] ) let signingEntityCheckingMode = SigningEntityCheckingMode.strict @@ -803,21 +855,23 @@ final class PackageSigningEntityTOFUTests: XCTestCase { let expectedFromVersion = Version("1.5.0") let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: (signingEntity: expectedSigningEntity, fromVersion: expectedFromVersion), - signers: [ - expectedSigningEntity: PackageSigner( - signingEntity: expectedSigningEntity, - origins: [.registry(registry.url)], - versions: [expectedFromVersion] - ), - signingEntity: PackageSigner( - signingEntity: signingEntity, - origins: [.registry(registry.url)], - versions: [existingVersion] - ), - ] - )] + [ + package.underlying: PackageSigners( + expectedSigner: (signingEntity: expectedSigningEntity, fromVersion: expectedFromVersion), + signers: [ + expectedSigningEntity: PackageSigner( + signingEntity: expectedSigningEntity, + origins: [.registry(registry.url)], + versions: [expectedFromVersion] + ), + signingEntity: PackageSigner( + signingEntity: signingEntity, + origins: [.registry(registry.url)], + versions: [existingVersion] + ), + ] + ) + ] ) let signingEntityCheckingMode = SigningEntityCheckingMode.strict @@ -867,21 +921,23 @@ final class PackageSigningEntityTOFUTests: XCTestCase { let expectedFromVersion = Version("1.5.0") let signingEntityStorage = MockPackageSigningEntityStorage( - [package.underlying: PackageSigners( - expectedSigner: (signingEntity: expectedSigningEntity, fromVersion: expectedFromVersion), - signers: [ - expectedSigningEntity: PackageSigner( - signingEntity: expectedSigningEntity, - origins: [.registry(registry.url)], - versions: [expectedFromVersion] - ), - signingEntity: PackageSigner( - signingEntity: signingEntity, - origins: [.registry(registry.url)], - versions: [existingVersion] - ), - ] - )] + [ + package.underlying: PackageSigners( + expectedSigner: (signingEntity: expectedSigningEntity, fromVersion: expectedFromVersion), + signers: [ + expectedSigningEntity: PackageSigner( + signingEntity: expectedSigningEntity, + origins: [.registry(registry.url)], + versions: [expectedFromVersion] + ), + signingEntity: PackageSigner( + signingEntity: signingEntity, + origins: [.registry(registry.url)], + versions: [existingVersion] + ), + ] + ) + ] ) let signingEntityCheckingMode = SigningEntityCheckingMode.strict @@ -902,14 +958,16 @@ final class PackageSigningEntityTOFUTests: XCTestCase { signingEntity: signingEntity ) ) { error in - guard case RegistryError.signingEntityForPackageChanged( - _, - _, - _, - let latest, - let previous, - let previousVersion - ) = error else { + guard + case RegistryError.signingEntityForPackageChanged( + _, + _, + _, + let latest, + let previous, + let previousVersion + ) = error + else { return XCTFail("Expected RegistryError.signingEntityForPackageChanged, got '\(error)'") } XCTAssertEqual(latest, signingEntity) @@ -939,7 +997,7 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = WriteConflictSigningEntityStorage() - let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change + let signingEntityCheckingMode = SigningEntityCheckingMode.strict // intended for this test; don't change let tofu = PackageSigningEntityTOFU( signingEntityStorage: signingEntityStorage, @@ -973,7 +1031,7 @@ final class PackageSigningEntityTOFUTests: XCTestCase { ) let signingEntityStorage = WriteConflictSigningEntityStorage() - let signingEntityCheckingMode = SigningEntityCheckingMode.warn // intended for this test; don't change + let signingEntityCheckingMode = SigningEntityCheckingMode.warn // intended for this test; don't change let tofu = PackageSigningEntityTOFU( signingEntityStorage: signingEntityStorage, diff --git a/Tests/PackageRegistryTests/PackageVersionChecksumTOFUTests.swift b/Tests/PackageRegistryTests/PackageVersionChecksumTOFUTests.swift index 798d39f48b8..ed07017924c 100644 --- a/Tests/PackageRegistryTests/PackageVersionChecksumTOFUTests.swift +++ b/Tests/PackageRegistryTests/PackageVersionChecksumTOFUTests.swift @@ -37,21 +37,21 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { XCTAssertEqual(request.headers.get("Accept").first, "application/vnd.swift.registry.v1+json") let data = """ - { - "id": "mona.LinkedList", - "version": "1.1.1", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "mona.LinkedList", + "version": "1.1.1", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "description": "One thing links to another." } - ], - "metadata": { - "description": "One thing links to another." } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -124,21 +124,21 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { XCTAssertEqual(request.headers.get("Accept").first, "application/vnd.swift.registry.v1+json") let data = """ - { - "id": "mona.LinkedList", - "version": "1.1.1", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "mona.LinkedList", + "version": "1.1.1", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "description": "One thing links to another." } - ], - "metadata": { - "description": "One thing links to another." } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -160,7 +160,7 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { configuration.defaultRegistry = registry let fingerprintStorage = WriteConflictFingerprintStorage() - let fingerprintCheckingMode = FingerprintCheckingMode.strict // intended for this test, don't change + let fingerprintCheckingMode = FingerprintCheckingMode.strict // intended for this test, don't change let registryClient = makeRegistryClient( configuration: configuration, @@ -206,21 +206,21 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { XCTAssertEqual(request.headers.get("Accept").first, "application/vnd.swift.registry.v1+json") let data = """ - { - "id": "mona.LinkedList", - "version": "1.1.1", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "mona.LinkedList", + "version": "1.1.1", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "description": "One thing links to another." } - ], - "metadata": { - "description": "One thing links to another." } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -242,7 +242,7 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { configuration.defaultRegistry = registry let fingerprintStorage = WriteConflictFingerprintStorage() - let fingerprintCheckingMode = FingerprintCheckingMode.warn // intended for this test, don't change + let fingerprintCheckingMode = FingerprintCheckingMode.warn // intended for this test, don't change let registryClient = makeRegistryClient( configuration: configuration, @@ -445,10 +445,10 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { origin: .registry(registryURL), value: checksum, contentType: .sourceCode - ), - ], - ], - ], + ) + ] + ] + ] ]) let fingerprintCheckingMode = FingerprintCheckingMode.strict @@ -500,12 +500,12 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { origin: .registry(registryURL), value: "non-matching checksum", contentType: .sourceCode - ), - ], - ], - ], + ) + ] + ] + ] ]) - let fingerprintCheckingMode = FingerprintCheckingMode.strict // intended for this test; don't change + let fingerprintCheckingMode = FingerprintCheckingMode.strict // intended for this test; don't change let registryClient = makeRegistryClient( configuration: configuration, @@ -563,12 +563,12 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { origin: .registry(registryURL), value: "non-matching checksum", contentType: .sourceCode - ), - ], - ], - ], + ) + ] + ] + ] ]) - let fingerprintCheckingMode = FingerprintCheckingMode.warn // intended for this test; don't change + let fingerprintCheckingMode = FingerprintCheckingMode.warn // intended for this test; don't change let registryClient = makeRegistryClient( configuration: configuration, @@ -641,7 +641,7 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { registry: registry, package: package, version: version, - toolsVersion: .v5_6, // Version specific manifest + toolsVersion: .v5_6, // Version specific manifest checksum: "Package@swift-5.6.swift checksum" ) @@ -649,7 +649,7 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { registry: registry, package: package, version: version, - toolsVersion: .none, // default manifest + toolsVersion: .none, // default manifest checksum: "Package.swift checksum" ) @@ -704,10 +704,10 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { origin: .registry(registryURL), value: checksum, contentType: contentType - ), - ], - ], - ], + ) + ] + ] + ] ]) let fingerprintCheckingMode = FingerprintCheckingMode.strict @@ -761,12 +761,12 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { origin: .registry(registryURL), value: "non-matching checksum", contentType: contentType - ), - ], - ], - ], + ) + ] + ] + ] ]) - let fingerprintCheckingMode = FingerprintCheckingMode.strict // intended for this test; don't change + let fingerprintCheckingMode = FingerprintCheckingMode.strict // intended for this test; don't change let registryClient = makeRegistryClient( configuration: configuration, @@ -826,12 +826,12 @@ final class PackageVersionChecksumTOFUTests: XCTestCase { origin: .registry(registryURL), value: "non-matching checksum", contentType: contentType - ), - ], - ], - ], + ) + ] + ] + ] ]) - let fingerprintCheckingMode = FingerprintCheckingMode.warn // intended for this test; don't change + let fingerprintCheckingMode = FingerprintCheckingMode.warn // intended for this test; don't change let registryClient = makeRegistryClient( configuration: configuration, @@ -933,7 +933,7 @@ private class WriteConflictFingerprintStorage: PackageFingerprintStorage { package: PackageReference, version: Version, observabilityScope: ObservabilityScope - ) throws -> [Fingerprint.Kind: [Fingerprint.ContentType: Fingerprint]]{ + ) throws -> [Fingerprint.Kind: [Fingerprint.ContentType: Fingerprint]] { try self.get( package: package.identity, version: version, diff --git a/Tests/PackageRegistryTests/RegistryClientTests.swift b/Tests/PackageRegistryTests/RegistryClientTests.swift index 32e65c1f150..177ce0bcd3e 100644 --- a/Tests/PackageRegistryTests/RegistryClientTests.swift +++ b/Tests/PackageRegistryTests/RegistryClientTests.swift @@ -45,32 +45,32 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+json") let data = #""" - { - "releases": { - "1.1.1": { - "url": "https://packages.example.com/mona/LinkedList/1.1.1" - }, - "1.1.0": { - "url": "https://packages.example.com/mona/LinkedList/1.1.0", - "problem": { - "status": 410, - "title": "Gone", - "detail": "this release was removed from the registry" + { + "releases": { + "1.1.1": { + "url": "https://packages.example.com/mona/LinkedList/1.1.1" + }, + "1.1.0": { + "url": "https://packages.example.com/mona/LinkedList/1.1.0", + "problem": { + "status": 410, + "title": "Gone", + "detail": "this release was removed from the registry" + } + }, + "1.0.0": { + "url": "https://packages.example.com/mona/LinkedList/1.0.0" } - }, - "1.0.0": { - "url": "https://packages.example.com/mona/LinkedList/1.0.0" } } - } - """#.data(using: .utf8)! + """#.data(using: .utf8)! let links = """ - ; rel="canonical", - ; rel="alternate", - ; rel="alternate", - ; rel="alternate" - """ + ; rel="canonical", + ; rel="alternate", + ; rel="alternate", + ; rel="alternate" + """ return .init( statusCode: 200, @@ -93,12 +93,14 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let assert: (RegistryClient.PackageMetadata) -> Void = { metadata in #expect(metadata.versions == ["1.1.1", "1.0.0"]) - #expect(metadata.alternateLocations == [ - SourceControlURL("https://github.com/mona/LinkedList"), - SourceControlURL("ssh://git@github.com:mona/LinkedList.git"), - SourceControlURL("git@github.com:mona/LinkedList.git"), - SourceControlURL("https://gitlab.com/mona/LinkedList"), - ]) + #expect( + metadata.alternateLocations == [ + SourceControlURL("https://github.com/mona/LinkedList"), + SourceControlURL("ssh://git@github.com:mona/LinkedList.git"), + SourceControlURL("git@github.com:mona/LinkedList.git"), + SourceControlURL("https://gitlab.com/mona/LinkedList"), + ] + ) } let registryClient = makeRegistryClient(configuration: configuration, httpClient: httpClient) @@ -131,47 +133,47 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch request.url { case releasesURL: data = #""" - { - "releases": { - "1.1.1": { - "url": "https://packages.example.com/mona/LinkedList/1.1.1" - }, - "1.1.0": { - "url": "https://packages.example.com/mona/LinkedList/1.1.0", - "problem": { - "status": 410, - "title": "Gone", - "detail": "this release was removed from the registry" + { + "releases": { + "1.1.1": { + "url": "https://packages.example.com/mona/LinkedList/1.1.1" + }, + "1.1.0": { + "url": "https://packages.example.com/mona/LinkedList/1.1.0", + "problem": { + "status": 410, + "title": "Gone", + "detail": "this release was removed from the registry" + } } } } - } - """#.data(using: .utf8)! + """#.data(using: .utf8)! links = """ - ; rel="canonical", - ; rel="alternate", - ; rel="alternate", - ; rel="alternate", - <\(releasesURLPage2)>; rel="next" - """ + ; rel="canonical", + ; rel="alternate", + ; rel="alternate", + ; rel="alternate", + <\(releasesURLPage2)>; rel="next" + """ case releasesURLPage2: data = #""" - { - "releases": { - "1.0.0": { - "url": "https://packages.example.com/mona/LinkedList/1.0.0" + { + "releases": { + "1.0.0": { + "url": "https://packages.example.com/mona/LinkedList/1.0.0" + } } } - } - """#.data(using: .utf8)! + """#.data(using: .utf8)! links = """ - ; rel="canonical", - ; rel="alternate", - ; rel="alternate", - ; rel="alternate" - """ + ; rel="canonical", + ; rel="alternate", + ; rel="alternate", + ; rel="alternate" + """ default: throw StringError("method and url should match") } @@ -195,12 +197,14 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let registryClient = makeRegistryClient(configuration: configuration, httpClient: httpClient) let metadata = try await registryClient.getPackageMetadata(package: identity) #expect(metadata.versions == ["1.1.1", "1.0.0"]) - #expect(metadata.alternateLocations == [ - SourceControlURL("https://github.com/mona/LinkedList"), - SourceControlURL("ssh://git@github.com:mona/LinkedList.git"), - SourceControlURL("git@github.com:mona/LinkedList.git"), - SourceControlURL("https://gitlab.com/mona/LinkedList"), - ]) + #expect( + metadata.alternateLocations == [ + SourceControlURL("https://github.com/mona/LinkedList"), + SourceControlURL("ssh://git@github.com:mona/LinkedList.git"), + SourceControlURL("git@github.com:mona/LinkedList.git"), + SourceControlURL("https://gitlab.com/mona/LinkedList"), + ] + ) } @Test func getPackageMetadataPaginatedCancellation() async throws { @@ -222,30 +226,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") fallthrough case releasesURL: data = #""" - { - "releases": { - "1.1.1": { - "url": "https://packages.example.com/mona/LinkedList/1.1.1" - }, - "1.1.0": { - "url": "https://packages.example.com/mona/LinkedList/1.1.0", - "problem": { - "status": 410, - "title": "Gone", - "detail": "this release was removed from the registry" + { + "releases": { + "1.1.1": { + "url": "https://packages.example.com/mona/LinkedList/1.1.1" + }, + "1.1.0": { + "url": "https://packages.example.com/mona/LinkedList/1.1.0", + "problem": { + "status": 410, + "title": "Gone", + "detail": "this release was removed from the registry" + } } } } - } - """#.data(using: .utf8)! + """#.data(using: .utf8)! links = """ - ; rel="canonical", - ; rel="alternate", - ; rel="alternate", - ; rel="alternate", - <\(releasesURLPage2)>; rel="next" - """ + ; rel="canonical", + ; rel="alternate", + ; rel="alternate", + ; rel="alternate", + <\(releasesURLPage2)>; rel="next" + """ default: throw StringError("method and url should match") } @@ -310,7 +314,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let serverErrorHandler = ServerErrorHandler( method: .get, url: releasesURL, - errorCode: Int.random(in: 405 ..< 500), + errorCode: Int.random(in: 405..<500), errorDescription: UUID().uuidString ) @@ -322,7 +326,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") await #expect { try await registryClient.getPackageMetadata(package: identity) } throws: { error in - if case RegistryError + if case + RegistryError .failedRetrievingReleases( registry: configuration.defaultRegistry!, package: identity, @@ -330,7 +335,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") code: serverErrorHandler.errorCode, details: serverErrorHandler.errorDescription ) - ) = error { + ) = error + { return true } return false @@ -365,30 +371,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+json") let data = #""" - { - "id": "mona.LinkedList", - "version": "1.1.1", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "a2ac54cf25fbc1ad0028f03f0aa4b96833b83bb05a14e510892bb27dea4dc812" + { + "id": "mona.LinkedList", + "version": "1.1.1", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "a2ac54cf25fbc1ad0028f03f0aa4b96833b83bb05a14e510892bb27dea4dc812" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """#.data(using: .utf8)! + """#.data(using: .utf8)! return .init( statusCode: 200, @@ -416,11 +422,13 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(metadata.author?.name == "J. Appleseed") #expect(metadata.licenseURL == URL("https://github.com/mona/LinkedList/license")) #expect(metadata.readmeURL == URL("https://github.com/mona/LinkedList/readme")) - #expect(metadata.repositoryURLs! == [ - SourceControlURL("https://github.com/mona/LinkedList"), - SourceControlURL("ssh://git@github.com:mona/LinkedList.git"), - SourceControlURL("git@github.com:mona/LinkedList.git"), - ]) + #expect( + metadata.repositoryURLs! == [ + SourceControlURL("https://github.com/mona/LinkedList"), + SourceControlURL("ssh://git@github.com:mona/LinkedList.git"), + SourceControlURL("git@github.com:mona/LinkedList.git"), + ] + ) } let registryClient = makeRegistryClient(configuration: configuration, httpClient: httpClient) @@ -444,7 +452,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let checksumAlgorithm: HashAlgorithm = MockHashAlgorithm() let expectedChecksums: [Version: String] = [ Version("1.1.1"): "a2ac54cf25fbc1ad0028f03f0aa4b96833b83bb05a14e510892bb27dea4dc812", - Version("1.1.0"): checksumAlgorithm.hash(emptyZipFile).hexadecimalRepresentation + Version("1.1.0"): checksumAlgorithm.hash(emptyZipFile).hexadecimalRepresentation, ] let counter = SendableBox(0) @@ -456,30 +464,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+json") let data = """ - { - "id": "mona.LinkedList", - "version": "1.1.1", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(expectedChecksum)" + { + "id": "mona.LinkedList", + "version": "1.1.1", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(expectedChecksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -495,30 +503,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+json") let data = """ - { - "id": "mona.LinkedList", - "version": "1.1.0", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(expectedChecksum)", + { + "id": "mona.LinkedList", + "version": "1.1.0", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(expectedChecksum)", + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -576,13 +584,15 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") await #expect { try await registryClient.getPackageVersionMetadata(package: identity, version: version) } throws: { error in - if case RegistryError + if case + RegistryError .failedRetrievingReleaseInfo( registry: configuration.defaultRegistry!, package: identity, version: version, error: RegistryError.packageVersionNotFound - ) = error { + ) = error + { return true } return false @@ -593,7 +603,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let serverErrorHandler = ServerErrorHandler( method: .get, url: releaseURL, - errorCode: Int.random(in: 405 ..< 500), + errorCode: Int.random(in: 405..<500), errorDescription: UUID().uuidString ) @@ -605,7 +615,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") await #expect { try await registryClient.getPackageVersionMetadata(package: identity, version: version) } throws: { error in - if case RegistryError + if case + RegistryError .failedRetrievingReleaseInfo( registry: configuration.defaultRegistry!, package: identity, @@ -614,7 +625,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") code: serverErrorHandler.errorCode, details: serverErrorHandler.errorDescription ) - ) = error { + ) = error + { return true } return false @@ -651,50 +663,50 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let checksum = checksumAlgorithm.hash(emptyZipFile).hexadecimalRepresentation let defaultManifest = """ - // swift-tools-version:5.5 - import PackageDescription - - let package = Package( - name: "LinkedList", - products: [ - .library(name: "LinkedList", targets: ["LinkedList"]) - ], - targets: [ - .target(name: "LinkedList"), - .testTarget(name: "LinkedListTests", dependencies: ["LinkedList"]), - ], - swiftLanguageVersions: [.v4, .v5] - ) - """ + // swift-tools-version:5.5 + import PackageDescription + + let package = Package( + name: "LinkedList", + products: [ + .library(name: "LinkedList", targets: ["LinkedList"]) + ], + targets: [ + .target(name: "LinkedList"), + .testTarget(name: "LinkedListTests", dependencies: ["LinkedList"]), + ], + swiftLanguageVersions: [.v4, .v5] + ) + """ let handler: HTTPClient.Implementation = { request, _ in switch (request.method, request.url) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -711,10 +723,10 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let defaultManifestData = Data(defaultManifest.utf8) let links = """ - ; rel="alternate"; filename="Package@swift-4.swift"; swift-tools-version="4.0", - ; rel="alternate"; filename="Package@swift-4.2.swift"; swift-tools-version="4.2", - ; rel="alternate"; filename="Package@swift-5.3.swift"; swift-tools-version="5.3" - """ + ; rel="alternate"; filename="Package@swift-4.swift"; swift-tools-version="4.0", + ; rel="alternate"; filename="Package@swift-4.2.swift"; swift-tools-version="4.2", + ; rel="alternate"; filename="Package@swift-5.3.swift"; swift-tools-version="5.3" + """ return .init( statusCode: 200, @@ -777,50 +789,50 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let checksum = checksumAlgorithm.hash(emptyZipFile).hexadecimalRepresentation let defaultManifest = """ - // swift-tools-version:5.5 - import PackageDescription - - let package = Package( - name: "LinkedList", - products: [ - .library(name: "LinkedList", targets: ["LinkedList"]) - ], - targets: [ - .target(name: "LinkedList"), - .testTarget(name: "LinkedListTests", dependencies: ["LinkedList"]), - ], - swiftLanguageVersions: [.v4, .v5] - ) - """ + // swift-tools-version:5.5 + import PackageDescription + + let package = Package( + name: "LinkedList", + products: [ + .library(name: "LinkedList", targets: ["LinkedList"]) + ], + targets: [ + .target(name: "LinkedList"), + .testTarget(name: "LinkedListTests", dependencies: ["LinkedList"]), + ], + swiftLanguageVersions: [.v4, .v5] + ) + """ let handler: HTTPClient.Implementation = { request, _ in switch (request.method, request.url) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -837,10 +849,10 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let defaultManifestData = Data(defaultManifest.utf8) let links = """ - ; rel="alternate"; filename="Package@swift-4.swift"; swift-tools-version="4.0", - ; rel="alternate"; filename="Package@swift-4.2.swift"; swift-tools-version="4.2", - ; rel="alternate"; filename="Package@swift-5.3.swift"; swift-tools-version="5.3" - """ + ; rel="alternate"; filename="Package@swift-4.swift"; swift-tools-version="4.0", + ; rel="alternate"; filename="Package@swift-4.2.swift"; swift-tools-version="4.2", + ; rel="alternate"; filename="Package@swift-5.3.swift"; swift-tools-version="5.3" + """ return .init( statusCode: 200, @@ -873,10 +885,10 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") origin: .registry(registryURL), value: manifestChecksum, contentType: contentType - ), - ], - ], - ], + ) + ] + ] + ] ]) let registryClient = makeRegistryClient( @@ -907,50 +919,50 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let checksum = checksumAlgorithm.hash(emptyZipFile).hexadecimalRepresentation let defaultManifest = """ - // swift-tools-version:5.5 - import PackageDescription - - let package = Package( - name: "LinkedList", - products: [ - .library(name: "LinkedList", targets: ["LinkedList"]) - ], - targets: [ - .target(name: "LinkedList"), - .testTarget(name: "LinkedListTests", dependencies: ["LinkedList"]), - ], - swiftLanguageVersions: [.v4, .v5] - ) - """ + // swift-tools-version:5.5 + import PackageDescription + + let package = Package( + name: "LinkedList", + products: [ + .library(name: "LinkedList", targets: ["LinkedList"]) + ], + targets: [ + .target(name: "LinkedList"), + .testTarget(name: "LinkedListTests", dependencies: ["LinkedList"]), + ], + swiftLanguageVersions: [.v4, .v5] + ) + """ let handler: HTTPClient.Implementation = { request, _ in switch (request.method, request.url) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -967,10 +979,10 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let defaultManifestData = Data(defaultManifest.utf8) let links = """ - ; rel="alternate"; filename="Package@swift-4.swift"; swift-tools-version="4.0", - ; rel="alternate"; filename="Package@swift-4.2.swift"; swift-tools-version="4.2", - ; rel="alternate"; filename="Package@swift-5.3.swift"; swift-tools-version="5.3" - """ + ; rel="alternate"; filename="Package@swift-4.swift"; swift-tools-version="4.0", + ; rel="alternate"; filename="Package@swift-4.2.swift"; swift-tools-version="4.2", + ; rel="alternate"; filename="Package@swift-5.3.swift"; swift-tools-version="5.3" + """ return .init( statusCode: 200, @@ -1001,17 +1013,17 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") origin: .registry(registryURL), value: "non-matching checksum", contentType: contentType - ), - ], - ], - ], + ) + ] + ] + ] ]) let registryClient = makeRegistryClient( configuration: configuration, httpClient: httpClient, fingerprintStorage: fingerprintStorage, - fingerprintCheckingMode: .strict, // intended for this test; don't change + fingerprintCheckingMode: .strict, // intended for this test; don't change checksumAlgorithm: checksumAlgorithm ) @@ -1034,50 +1046,50 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let checksum = checksumAlgorithm.hash(emptyZipFile).hexadecimalRepresentation let defaultManifest = """ - // swift-tools-version:5.5 - import PackageDescription - - let package = Package( - name: "LinkedList", - products: [ - .library(name: "LinkedList", targets: ["LinkedList"]) - ], - targets: [ - .target(name: "LinkedList"), - .testTarget(name: "LinkedListTests", dependencies: ["LinkedList"]), - ], - swiftLanguageVersions: [.v4, .v5] - ) - """ + // swift-tools-version:5.5 + import PackageDescription + + let package = Package( + name: "LinkedList", + products: [ + .library(name: "LinkedList", targets: ["LinkedList"]) + ], + targets: [ + .target(name: "LinkedList"), + .testTarget(name: "LinkedListTests", dependencies: ["LinkedList"]), + ], + swiftLanguageVersions: [.v4, .v5] + ) + """ let handler: HTTPClient.Implementation = { request, _ in switch (request.method, request.url) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1094,10 +1106,10 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let defaultManifestData = Data(defaultManifest.utf8) let links = """ - ; rel="alternate"; filename="Package@swift-4.swift"; swift-tools-version="4.0", - ; rel="alternate"; filename="Package@swift-4.2.swift"; swift-tools-version="4.2", - ; rel="alternate"; filename="Package@swift-5.3.swift"; swift-tools-version="5.3" - """ + ; rel="alternate"; filename="Package@swift-4.swift"; swift-tools-version="4.0", + ; rel="alternate"; filename="Package@swift-4.2.swift"; swift-tools-version="4.2", + ; rel="alternate"; filename="Package@swift-5.3.swift"; swift-tools-version="5.3" + """ return .init( statusCode: 200, @@ -1128,17 +1140,17 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") origin: .registry(registryURL), value: "non-matching checksum", contentType: contentType - ), - ], - ], - ], + ) + ] + ] + ] ]) let registryClient = makeRegistryClient( configuration: configuration, httpClient: httpClient, fingerprintStorage: fingerprintStorage, - fingerprintCheckingMode: .warn, // intended for this test; don't change + fingerprintCheckingMode: .warn, // intended for this test; don't change checksumAlgorithm: checksumAlgorithm ) @@ -1178,13 +1190,13 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.kind, request.method, request.url) { case (.generic, .get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [], - "metadata": {} - } - """.data(using: .utf8)! + { + "id": "\(identity)", + "version": "\(version)", + "resources": [], + "metadata": {} + } + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1228,7 +1240,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let serverErrorHandler = ServerErrorHandler( method: .get, url: manifestURL, - errorCode: Int.random(in: 405 ..< 500), + errorCode: Int.random(in: 405..<500), errorDescription: UUID().uuidString ) @@ -1236,13 +1248,13 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.method, request.url) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [], - "metadata": {} - } - """.data(using: .utf8)! + { + "id": "\(identity)", + "version": "\(version)", + "resources": [], + "metadata": {} + } + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1313,7 +1325,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") @Test(arguments: [ (toolsVersion: ToolsVersion.v5_3, expectedToolsVersion: ToolsVersion.v5_3), (toolsVersion: ToolsVersion.v4, expectedToolsVersion: ToolsVersion.v4), - (toolsVersion: nil, expectedToolsVersion: ToolsVersion.current) + (toolsVersion: nil, expectedToolsVersion: ToolsVersion.current), ]) func getManifestContent(toolsVersion: ToolsVersion?, expectedToolsVersion: ToolsVersion) async throws { let checksumAlgorithm: HashAlgorithm = MockHashAlgorithm() @@ -1321,7 +1333,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let handler: HTTPClient.Implementation = { request, _ in var components = URLComponents(url: request.url, resolvingAgainstBaseURL: false)! - let toolsVersion = components.queryItems?.first { $0.name == "swift-version" } + let toolsVersion = + components.queryItems?.first { $0.name == "swift-version" } .flatMap { ToolsVersion(string: $0.value!) } ?? ToolsVersion.current // remove query components.query = nil @@ -1329,30 +1342,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.method, urlWithoutQuery) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1367,12 +1380,12 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+swift") let data = """ - // swift-tools-version:\(toolsVersion) + // swift-tools-version:\(toolsVersion) - import PackageDescription + import PackageDescription - let package = Package() - """.data(using: .utf8)! + let package = Package() + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1426,7 +1439,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") @Test(arguments: [ (toolsVersion: ToolsVersion.v5_3, expectedToolsVersion: ToolsVersion.v5_3), - (toolsVersion: nil, expectedToolsVersion: ToolsVersion.current) + (toolsVersion: nil, expectedToolsVersion: ToolsVersion.current), ]) func getManifestContentWithOptionalContentVersion(toolsVersion: ToolsVersion?, expectedToolsVersion: ToolsVersion) async throws { let checksumAlgorithm: HashAlgorithm = MockHashAlgorithm() @@ -1434,7 +1447,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let handler: HTTPClient.Implementation = { request, _ in var components = URLComponents(url: request.url, resolvingAgainstBaseURL: false)! - let toolsVersion = components.queryItems?.first { $0.name == "swift-version" } + let toolsVersion = + components.queryItems?.first { $0.name == "swift-version" } .flatMap { ToolsVersion(string: $0.value!) } ?? ToolsVersion.current // remove query components.query = nil @@ -1442,30 +1456,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.method, urlWithoutQuery) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1480,12 +1494,12 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+swift") let data = """ - // swift-tools-version:\(toolsVersion) + // swift-tools-version:\(toolsVersion) - import PackageDescription + import PackageDescription - let package = Package() - """.data(using: .utf8)! + let package = Package() + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1525,7 +1539,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") @Test(arguments: [ (toolsVersion: ToolsVersion.v5_3, expectedToolsVersion: ToolsVersion.v5_3), - (toolsVersion: nil, expectedToolsVersion: ToolsVersion.current) + (toolsVersion: nil, expectedToolsVersion: ToolsVersion.current), ]) func getManifestContentMatchingChecksumInStorage(toolsVersion: ToolsVersion?, expectedToolsVersion: ToolsVersion) async throws { let checksumAlgorithm: HashAlgorithm = MockHashAlgorithm() @@ -1533,7 +1547,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let handler: HTTPClient.Implementation = { request, _ in var components = URLComponents(url: request.url, resolvingAgainstBaseURL: false)! - let toolsVersion = components.queryItems?.first { $0.name == "swift-version" } + let toolsVersion = + components.queryItems?.first { $0.name == "swift-version" } .flatMap { ToolsVersion(string: $0.value!) } ?? ToolsVersion.current // remove query components.query = nil @@ -1541,30 +1556,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.method, urlWithoutQuery) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1599,9 +1614,11 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") configuration.defaultRegistry = Registry(url: registryURL, supportsAvailability: false) configuration.security = .testDefault - let defaultManifestChecksum = checksumAlgorithm + let defaultManifestChecksum = + checksumAlgorithm .hash(.init(Data(manifestContent(toolsVersion: .none).utf8))).hexadecimalRepresentation - let versionManifestChecksum = checksumAlgorithm + let versionManifestChecksum = + checksumAlgorithm .hash(.init(Data(manifestContent(toolsVersion: .v5_3).utf8))).hexadecimalRepresentation let fingerprintStorage = MockPackageFingerprintStorage([ identity: [ @@ -1617,9 +1634,9 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") value: versionManifestChecksum, contentType: Fingerprint.ContentType.manifest(.v5_3) ), - ], - ], - ], + ] + ] + ] ]) let registryClient = makeRegistryClient( @@ -1648,7 +1665,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let handler: HTTPClient.Implementation = { request, _ in var components = URLComponents(url: request.url, resolvingAgainstBaseURL: false)! - let toolsVersion = components.queryItems?.first { $0.name == "swift-version" } + let toolsVersion = + components.queryItems?.first { $0.name == "swift-version" } .flatMap { ToolsVersion(string: $0.value!) } ?? ToolsVersion.current // remove query components.query = nil @@ -1656,30 +1674,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.method, urlWithoutQuery) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1728,16 +1746,16 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") value: "non-matching checksum", contentType: Fingerprint.ContentType.manifest(.v5_3) ), - ], - ], - ], + ] + ] + ] ]) let registryClient = makeRegistryClient( configuration: configuration, httpClient: httpClient, fingerprintStorage: fingerprintStorage, - fingerprintCheckingMode: .strict, // intended for this test; don't change + fingerprintCheckingMode: .strict, // intended for this test; don't change checksumAlgorithm: checksumAlgorithm ) @@ -1757,7 +1775,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") @Test(arguments: [ (toolsVersion: ToolsVersion.v5_3, expectedToolsVersion: ToolsVersion.v5_3), - (toolsVersion: nil, expectedToolsVersion: ToolsVersion.current) + (toolsVersion: nil, expectedToolsVersion: ToolsVersion.current), ]) func getManifestContentWithNonMatchingChecksumInStorage_warn(toolsVersion: ToolsVersion?, expectedToolsVersion: ToolsVersion) async throws { let checksumAlgorithm: HashAlgorithm = MockHashAlgorithm() @@ -1765,7 +1783,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let handler: HTTPClient.Implementation = { request, _ in var components = URLComponents(url: request.url, resolvingAgainstBaseURL: false)! - let toolsVersion = components.queryItems?.first { $0.name == "swift-version" } + let toolsVersion = + components.queryItems?.first { $0.name == "swift-version" } .flatMap { ToolsVersion(string: $0.value!) } ?? ToolsVersion.current // remove query components.query = nil @@ -1773,30 +1792,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.method, urlWithoutQuery) { case (.get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1845,16 +1864,16 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") value: "non-matching checksum", contentType: Fingerprint.ContentType.manifest(.v5_3) ), - ], - ], - ], + ] + ] + ] ]) let registryClient = makeRegistryClient( configuration: configuration, httpClient: httpClient, fingerprintStorage: fingerprintStorage, - fingerprintCheckingMode: .warn, // intended for this test; don't change + fingerprintCheckingMode: .warn, // intended for this test; don't change checksumAlgorithm: checksumAlgorithm ) @@ -1891,13 +1910,13 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.kind, request.method, request.url) { case (.generic, .get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [], - "metadata": {} - } - """.data(using: .utf8)! + { + "id": "\(identity)", + "version": "\(version)", + "resources": [], + "metadata": {} + } + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1941,7 +1960,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let serverErrorHandler = ServerErrorHandler( method: .get, url: manifestURL, - errorCode: Int.random(in: 405 ..< 500), + errorCode: Int.random(in: 405..<500), errorDescription: UUID().uuidString ) @@ -1949,13 +1968,13 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.kind, request.method, request.url) { case (.generic, .get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [], - "metadata": {} - } - """.data(using: .utf8)! + { + "id": "\(identity)", + "version": "\(version)", + "resources": [], + "metadata": {} + } + """.data(using: .utf8)! return .init( statusCode: 200, @@ -2040,26 +2059,26 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.kind, request.method, request.url) { case (.generic, .get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "\(author)" + }, + "licenseURL": "\(licenseURL)", + "readmeURL": "\(readmeURL)", + "repositoryURLs": [\"\(repositoryURLs.map(\.absoluteString).joined(separator: "\", \""))\"] } - ], - "metadata": { - "author": { - "name": "\(author)" - }, - "licenseURL": "\(licenseURL)", - "readmeURL": "\(readmeURL)", - "repositoryURLs": [\"\(repositoryURLs.map(\.absoluteString).joined(separator: "\", \""))\"] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -2177,30 +2196,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.kind, request.method, request.url) { case (.generic, .get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -2249,10 +2268,10 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") origin: .registry(registryURL), value: checksum, contentType: .sourceCode - ), - ], - ], - ], + ) + ] + ] + ] ]) let registryClient = RegistryClient( configuration: configuration, @@ -2299,30 +2318,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.kind, request.method, request.url) { case (.generic, .get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -2371,15 +2390,15 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") origin: .registry(registryURL), value: "non-matching checksum", contentType: .sourceCode - ), - ], - ], - ], + ) + ] + ] + ] ]) let registryClient = RegistryClient( configuration: configuration, fingerprintStorage: fingerprintStorage, - fingerprintCheckingMode: .strict, // intended for this test; don't change + fingerprintCheckingMode: .strict, // intended for this test; don't change skipSignatureValidation: false, signingEntityStorage: .none, signingEntityCheckingMode: .strict, @@ -2428,30 +2447,30 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.kind, request.method, request.url) { case (.generic, .get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "\(identity)", + "version": "\(version)", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "author": { + "name": "J. Appleseed" + }, + "licenseURL": "https://github.com/mona/LinkedList/license", + "readmeURL": "https://github.com/mona/LinkedList/readme", + "repositoryURLs": [ + "https://github.com/mona/LinkedList", + "ssh://git@github.com:mona/LinkedList.git", + "git@github.com:mona/LinkedList.git" + ] } - ], - "metadata": { - "author": { - "name": "J. Appleseed" - }, - "licenseURL": "https://github.com/mona/LinkedList/license", - "readmeURL": "https://github.com/mona/LinkedList/readme", - "repositoryURLs": [ - "https://github.com/mona/LinkedList", - "ssh://git@github.com:mona/LinkedList.git", - "git@github.com:mona/LinkedList.git" - ] } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -2500,15 +2519,15 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") origin: .registry(registryURL), value: "non-matching checksum", contentType: .sourceCode - ), - ], - ], - ], + ) + ] + ] + ] ]) let registryClient = RegistryClient( configuration: configuration, fingerprintStorage: fingerprintStorage, - fingerprintCheckingMode: .warn, // intended for this test; don't change + fingerprintCheckingMode: .warn, // intended for this test; don't change skipSignatureValidation: false, signingEntityStorage: .none, signingEntityCheckingMode: .strict, @@ -2577,26 +2596,26 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") ]), body: nil ) - // `downloadSourceArchive` calls this API to fetch checksum + // `downloadSourceArchive` calls this API to fetch checksum case (.generic, .get, metadataURL): #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+json") let data = """ - { - "id": "mona.LinkedList", - "version": "1.1.1", - "resources": [ { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + "id": "mona.LinkedList", + "version": "1.1.1", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "description": "One thing links to another." } - ], - "metadata": { - "description": "One thing links to another." - } - } - """.data(using: .utf8)! + } + """.data(using: .utf8)! return .init( statusCode: 200, @@ -2693,26 +2712,26 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") ]), body: nil ) - // `downloadSourceArchive` calls this API to fetch checksum + // `downloadSourceArchive` calls this API to fetch checksum case (.generic, .get, metadataURL): #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+json") let data = """ - { - "id": "mona.LinkedList", - "version": "1.1.1", - "resources": [ { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + "id": "mona.LinkedList", + "version": "1.1.1", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "description": "One thing links to another." } - ], - "metadata": { - "description": "One thing links to another." - } - } - """.data(using: .utf8)! + } + """.data(using: .utf8)! return .init( statusCode: 200, @@ -2784,13 +2803,13 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.kind, request.method, request.url) { case (.generic, .get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [], - "metadata": {} - } - """.data(using: .utf8)! + { + "id": "\(identity)", + "version": "\(version)", + "resources": [], + "metadata": {} + } + """.data(using: .utf8)! return .init( statusCode: 200, @@ -2833,13 +2852,15 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") destinationPath: path ) } throws: { error in - if case RegistryError + if case + RegistryError .failedDownloadingSourceArchive( registry: configuration.defaultRegistry!, package: identity, version: version, error: RegistryError.packageVersionNotFound - ) = error { + ) = error + { return true } return false @@ -2850,7 +2871,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let serverErrorHandler = ServerErrorHandler( method: .get, url: downloadURL, - errorCode: Int.random(in: 405 ..< 500), + errorCode: Int.random(in: 405..<500), errorDescription: UUID().uuidString ) @@ -2858,13 +2879,13 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") switch (request.kind, request.method, request.url) { case (.generic, .get, metadataURL): let data = """ - { - "id": "\(identity)", - "version": "\(version)", - "resources": [], - "metadata": {} - } - """.data(using: .utf8)! + { + "id": "\(identity)", + "version": "\(version)", + "resources": [], + "metadata": {} + } + """.data(using: .utf8)! return .init( statusCode: 200, @@ -2907,13 +2928,15 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") destinationPath: path ) } throws: { error in - if case RegistryError + if case + RegistryError .failedDownloadingSourceArchive( registry: configuration.defaultRegistry!, package: identity, version: version, error: RegistryError.serverError(code: serverErrorHandler.errorCode, details: serverErrorHandler.errorDescription) - ) = error { + ) = error + { return true } return false @@ -2967,12 +2990,12 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+json") let data = #""" - { - "identifiers": [ - "mona.LinkedList" - ] - } - """#.data(using: .utf8)! + { + "identifiers": [ + "mona.LinkedList" + ] + } + """#.data(using: .utf8)! return .init( statusCode: 200, @@ -3031,7 +3054,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let serverErrorHandler = ServerErrorHandler( method: .get, url: identifiersURL, - errorCode: Int.random(in: 405 ..< 500), // avoid 404 since it is not considered an error + errorCode: Int.random(in: 405..<500), // avoid 404 since it is not considered an error errorDescription: UUID().uuidString ) @@ -3064,12 +3087,12 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+json") let data = #""" - { - "identifiers": [ - "mona.LinkedList" - ] - } - """#.data(using: .utf8)! + { + "identifiers": [ + "mona.LinkedList" + ] + } + """#.data(using: .utf8)! return .init( statusCode: 200, @@ -3112,12 +3135,12 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") #expect(request.headers.get("Accept").first == "application/vnd.swift.registry.v1+json") let data = #""" - { - "identifiers": [ - "mona.LinkedList" - ] - } - """#.data(using: .utf8)! + { + "identifiers": [ + "mona.LinkedList" + ] + } + """#.data(using: .utf8)! return .init( statusCode: 200, @@ -3164,7 +3187,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") return .init( statusCode: 200, headers: .init([ - .init(name: "Content-Version", value: "1"), + .init(name: "Content-Version", value: "1") ]) ) default: @@ -3207,7 +3230,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") return .init( statusCode: 401, headers: .init([ - .init(name: "Content-Version", value: "1"), + .init(name: "Content-Version", value: "1") ]) ) default: @@ -3247,7 +3270,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") return .init( statusCode: 501, headers: .init([ - .init(name: "Content-Version", value: "1"), + .init(name: "Content-Version", value: "1") ]) ) default: @@ -3282,7 +3305,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") @Suite("Registry Publishing") struct RegistryPublishing { @Test func publishSync() async throws { let expectedLocation = - URL("https://\(registryURL)/packages\(identity.registry!.scope)/\(identity.registry!.name)/\(version)") + URL("https://\(registryURL)/packages\(identity.registry!.scope)/\(identity.registry!.name)/\(version)") let archiveContent = UUID().uuidString let metadataContent = UUID().uuidString @@ -3346,8 +3369,8 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") @Test func publishAsync() async throws { let expectedLocation = - URL("https://\(registryURL)/status\(identity.registry!.scope)/\(identity.registry!.name)/\(version)") - let expectedRetry = Int.random(in: 10 ..< 100) + URL("https://\(registryURL)/status\(identity.registry!.scope)/\(identity.registry!.name)/\(version)") + let expectedRetry = Int.random(in: 10..<100) let archiveContent = UUID().uuidString let metadataContent = UUID().uuidString @@ -3407,7 +3430,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") @Test func publishWithSignature() async throws { let expectedLocation = - URL("https://\(registryURL)/packages\(identity.registry!.scope)/\(identity.registry!.name)/\(version)") + URL("https://\(registryURL)/packages\(identity.registry!.scope)/\(identity.registry!.name)/\(version)") let archiveContent = UUID().uuidString let metadataContent = UUID().uuidString @@ -3602,7 +3625,7 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") let serverErrorHandler = ServerErrorHandler( method: .put, url: publishURL, - errorCode: Int.random(in: 405 ..< 500), + errorCode: Int.random(in: 405..<500), errorDescription: UUID().uuidString ) @@ -3631,14 +3654,16 @@ fileprivate var availabilityURL = URL("\(registryURL)/availability") fileSystem: localFileSystem ) } throws: { error in - if case RegistryError + if case + RegistryError .failedPublishing( RegistryError .serverError( code: serverErrorHandler.errorCode, details: serverErrorHandler.errorDescription ) - ) = error { + ) = error + { return true } return false @@ -4072,14 +4097,12 @@ struct ServerErrorHandler { progress: HTTPClient.ProgressHandler? ) async throws -> HTTPClient.Response { let data = """ - { - "detail": "\(self.errorDescription)" - } - """.data(using: .utf8)! + { + "detail": "\(self.errorDescription)" + } + """.data(using: .utf8)! - if request.method == self.method && - request.url == self.url - { + if request.method == self.method && request.url == self.url { return .init( statusCode: self.errorCode, headers: .init([ diff --git a/Tests/PackageRegistryTests/RegistryConfigurationTests.swift b/Tests/PackageRegistryTests/RegistryConfigurationTests.swift index f413b4f31fe..21204165e0a 100644 --- a/Tests/PackageRegistryTests/RegistryConfigurationTests.swift +++ b/Tests/PackageRegistryTests/RegistryConfigurationTests.swift @@ -96,13 +96,13 @@ final class RegistryConfigurationTests: XCTestCase { func testDecodeEmptyConfiguration() throws { let json = #""" - { - "registries": {}, - "authentication": {}, - "security": {}, - "version": 1 - } - """# + { + "registries": {}, + "authentication": {}, + "security": {}, + "version": 1 + } + """# let configuration = try decoder.decode(RegistryConfiguration.self, from: json) XCTAssertNil(configuration.defaultRegistry) @@ -113,11 +113,11 @@ final class RegistryConfigurationTests: XCTestCase { func testDecodeEmptyConfigurationWithMissingKeys() throws { let json = #""" - { - "registries": {}, - "version": 1 - } - """# + { + "registries": {}, + "version": 1 + } + """# let configuration = try decoder.decode(RegistryConfiguration.self, from: json) XCTAssertNil(configuration.defaultRegistry) @@ -128,71 +128,71 @@ final class RegistryConfigurationTests: XCTestCase { func testDecodeExampleConfiguration() throws { let json = #""" - { - "registries": { - "[default]": { - "url": "\#(defaultRegistryBaseURL)" - }, - "foo": { - "url": "\#(customRegistryBaseURL)" - }, - "bar": { - "url": "\#(customRegistryBaseURL)" - } - }, - "authentication": { - "packages.example.com": { - "type": "basic", - "loginAPIPath": "/v1/login" - } - }, - "security": { - "default": { - "signing": { - "onUnsigned": "error", - "onUntrustedCertificate": "error", - "trustedRootCertificatesPath": "~/.swiftpm/security/trusted-root-certs/", - "includeDefaultTrustedRootCertificates": true, - "validationChecks": { - "certificateExpiration": "disabled", - "certificateRevocation": "disabled" - } + { + "registries": { + "[default]": { + "url": "\#(defaultRegistryBaseURL)" + }, + "foo": { + "url": "\#(customRegistryBaseURL)" + }, + "bar": { + "url": "\#(customRegistryBaseURL)" } }, - "registryOverrides": { + "authentication": { "packages.example.com": { + "type": "basic", + "loginAPIPath": "/v1/login" + } + }, + "security": { + "default": { "signing": { - "onUnsigned": "warn", - "onUntrustedCertificate": "warn", - "trustedRootCertificatesPath": "/foo/roots", - "includeDefaultTrustedRootCertificates": false, + "onUnsigned": "error", + "onUntrustedCertificate": "error", + "trustedRootCertificatesPath": "~/.swiftpm/security/trusted-root-certs/", + "includeDefaultTrustedRootCertificates": true, "validationChecks": { - "certificateExpiration": "enabled", - "certificateRevocation": "allowSoftFail" + "certificateExpiration": "disabled", + "certificateRevocation": "disabled" } } - } - }, - "scopeOverrides": { - "mona": { - "signing": { - "trustedRootCertificatesPath": "/mona/roots", - "includeDefaultTrustedRootCertificates": false + }, + "registryOverrides": { + "packages.example.com": { + "signing": { + "onUnsigned": "warn", + "onUntrustedCertificate": "warn", + "trustedRootCertificatesPath": "/foo/roots", + "includeDefaultTrustedRootCertificates": false, + "validationChecks": { + "certificateExpiration": "enabled", + "certificateRevocation": "allowSoftFail" + } + } } - } - }, - "packageOverrides": { - "mona.LinkedList": { - "signing": { - "trustedRootCertificatesPath": "/mona/LinkedList/roots", - "includeDefaultTrustedRootCertificates": false + }, + "scopeOverrides": { + "mona": { + "signing": { + "trustedRootCertificatesPath": "/mona/roots", + "includeDefaultTrustedRootCertificates": false + } + } + }, + "packageOverrides": { + "mona.LinkedList": { + "signing": { + "trustedRootCertificatesPath": "/mona/LinkedList/roots", + "includeDefaultTrustedRootCertificates": false + } } } - } - }, - "version": 1 - } - """# + }, + "version": 1 + } + """# let configuration = try decoder.decode(RegistryConfiguration.self, from: json) XCTAssertEqual(configuration.defaultRegistry?.url, defaultRegistryBaseURL) @@ -257,115 +257,115 @@ final class RegistryConfigurationTests: XCTestCase { func testDecodeConfigurationWithInvalidRegistryKey() throws { let json = #""" - { - "registries": { - 0: "\#(customRegistryBaseURL)" - }, - "version": 1 - } - """# + { + "registries": { + 0: "\#(customRegistryBaseURL)" + }, + "version": 1 + } + """# XCTAssertThrowsError(try self.decoder.decode(RegistryConfiguration.self, from: json)) } func testDecodeConfigurationWithInvalidRegistryValue() throws { let json = #""" - { - "registries": { - "[default]": "\#(customRegistryBaseURL)" - }, - "version": 1 - } - """# + { + "registries": { + "[default]": "\#(customRegistryBaseURL)" + }, + "version": 1 + } + """# XCTAssertThrowsError(try self.decoder.decode(RegistryConfiguration.self, from: json)) } func testDecodeConfigurationWithInvalidAuthenticationType() throws { let json = #""" - { - "registries": {}, - "authentication": { - "packages.example.com": { - "type": "foobar" - } - }, - "version": 1 - } - """# + { + "registries": {}, + "authentication": { + "packages.example.com": { + "type": "foobar" + } + }, + "version": 1 + } + """# XCTAssertThrowsError(try self.decoder.decode(RegistryConfiguration.self, from: json)) } func testDecodeConfigurationWithMissingVersion() throws { let json = #""" - { - "registries": {} - } - """# + { + "registries": {} + } + """# XCTAssertThrowsError(try self.decoder.decode(RegistryConfiguration.self, from: json)) } func testDecodeSecurityConfigurationWithInvalidScopeKey() throws { let json = #""" - { - "registries": {}, - "authentication": { - "packages.example.com": { - "type": "foobar" - } - }, - "security": { - "scopeOverrides": { - "mona.": { - "signing": { - "trustedRootCertificatesPath": "/mona/roots", - "includeDefaultTrustedRootCertificates": false + { + "registries": {}, + "authentication": { + "packages.example.com": { + "type": "foobar" + } + }, + "security": { + "scopeOverrides": { + "mona.": { + "signing": { + "trustedRootCertificatesPath": "/mona/roots", + "includeDefaultTrustedRootCertificates": false + } + } } - } - } - }, - "version": 1 - } - """# + }, + "version": 1 + } + """# XCTAssertThrowsError(try self.decoder.decode(RegistryConfiguration.self, from: json)) } func testDecodeSecurityConfigurationWithInvalidPackageKey() throws { let json = #""" - { - "registries": {}, - "authentication": { - "packages.example.com": { - "type": "foobar" - } - }, - "security": { - "packageOverrides": { - "LinkedList": { - "signing": { - "trustedRootCertificatesPath": "/mona/LinkedList/roots", - "includeDefaultTrustedRootCertificates": false + { + "registries": {}, + "authentication": { + "packages.example.com": { + "type": "foobar" + } + }, + "security": { + "packageOverrides": { + "LinkedList": { + "signing": { + "trustedRootCertificatesPath": "/mona/LinkedList/roots", + "includeDefaultTrustedRootCertificates": false + } + } } - } - } - }, - "version": 1 - } - """# + }, + "version": 1 + } + """# XCTAssertThrowsError(try self.decoder.decode(RegistryConfiguration.self, from: json)) } func testDecodeConfigurationWithInvalidVersion() throws { let json = #""" - { - "registries": {}, - "version": 999 - } - """# + { + "registries": {}, + "version": 999 + } + """# XCTAssertThrowsError(try self.decoder.decode(RegistryConfiguration.self, from: json)) } @@ -380,11 +380,11 @@ final class RegistryConfigurationTests: XCTestCase { func testGetSigning_noOverrides() throws { let json = #""" - { - "registries": {}, - "version": 1 - } - """# + { + "registries": {}, + "version": 1 + } + """# let configuration = try decoder.decode(RegistryConfiguration.self, from: json) @@ -402,22 +402,22 @@ final class RegistryConfigurationTests: XCTestCase { func testGetSigning_globalOverride() throws { let json = #""" - { - "registries": {}, - "security": { - "default": { - "signing": { - "onUnsigned": "error", - "trustedRootCertificatesPath": "/custom/roots", - "validationChecks": { - "certificateExpiration": "enabled" + { + "registries": {}, + "security": { + "default": { + "signing": { + "onUnsigned": "error", + "trustedRootCertificatesPath": "/custom/roots", + "validationChecks": { + "certificateExpiration": "enabled" + } } } - } - }, - "version": 1 - } - """# + }, + "version": 1 + } + """# let configuration = try decoder.decode(RegistryConfiguration.self, from: json) @@ -435,29 +435,29 @@ final class RegistryConfigurationTests: XCTestCase { func testGetSigning_registryOverride() throws { let json = #""" - { - "registries": {}, - "security": { - "registryOverrides": { - "packages.example.com": { - "signing": { - "onUntrustedCertificate": "warn", - "trustedRootCertificatesPath": "/foo/roots", - "validationChecks": { - "certificateRevocation": "allowSoftFail" + { + "registries": {}, + "security": { + "registryOverrides": { + "packages.example.com": { + "signing": { + "onUntrustedCertificate": "warn", + "trustedRootCertificatesPath": "/foo/roots", + "validationChecks": { + "certificateRevocation": "allowSoftFail" + } + } + }, + "other.example.com": { + "signing": { + "onUntrustedCertificate": "error" } - } - }, - "other.example.com": { - "signing": { - "onUntrustedCertificate": "error" } } - } - }, - "version": 1 - } - """# + }, + "version": 1 + } + """# let configuration = try decoder.decode(RegistryConfiguration.self, from: json) @@ -475,25 +475,25 @@ final class RegistryConfigurationTests: XCTestCase { func testGetSigning_scopeOverride() throws { let json = #""" - { - "registries": {}, - "security": { - "scopeOverrides": { - "mona": { - "signing": { - "trustedRootCertificatesPath": "/mona/roots" - } - }, - "foo": { - "signing": { - "trustedRootCertificatesPath": "/foo/roots" + { + "registries": {}, + "security": { + "scopeOverrides": { + "mona": { + "signing": { + "trustedRootCertificatesPath": "/mona/roots" + } + }, + "foo": { + "signing": { + "trustedRootCertificatesPath": "/foo/roots" + } } } - } - }, - "version": 1 - } - """# + }, + "version": 1 + } + """# let configuration = try decoder.decode(RegistryConfiguration.self, from: json) @@ -511,25 +511,25 @@ final class RegistryConfigurationTests: XCTestCase { func testGetSigning_packageOverride() throws { let json = #""" - { - "registries": {}, - "security": { - "packageOverrides": { - "mona.LinkedList": { - "signing": { - "trustedRootCertificatesPath": "/mona/linkedlist/roots" - } - }, - "foo.bar": { - "signing": { - "trustedRootCertificatesPath": "/foo/bar/roots" + { + "registries": {}, + "security": { + "packageOverrides": { + "mona.LinkedList": { + "signing": { + "trustedRootCertificatesPath": "/mona/linkedlist/roots" + } + }, + "foo.bar": { + "signing": { + "trustedRootCertificatesPath": "/foo/bar/roots" + } } } - } - }, - "version": 1 - } - """# + }, + "version": 1 + } + """# let configuration = try decoder.decode(RegistryConfiguration.self, from: json) @@ -547,39 +547,39 @@ final class RegistryConfigurationTests: XCTestCase { func testGetSigning_multipleOverrides() throws { let json = #""" - { - "registries": {}, - "security": { - "default": { - "signing": { - "trustedRootCertificatesPath": "/custom/roots" - } - }, - "registryOverrides": { - "packages.example.com": { + { + "registries": {}, + "security": { + "default": { "signing": { - "trustedRootCertificatesPath": "/foo/roots" + "trustedRootCertificatesPath": "/custom/roots" } - } - }, - "scopeOverrides": { - "mona": { - "signing": { - "trustedRootCertificatesPath": "/mona/roots" + }, + "registryOverrides": { + "packages.example.com": { + "signing": { + "trustedRootCertificatesPath": "/foo/roots" + } } - } - }, - "packageOverrides": { - "mona.LinkedList": { - "signing": { - "trustedRootCertificatesPath": "/mona/linkedlist/roots" + }, + "scopeOverrides": { + "mona": { + "signing": { + "trustedRootCertificatesPath": "/mona/roots" + } + } + }, + "packageOverrides": { + "mona.LinkedList": { + "signing": { + "trustedRootCertificatesPath": "/mona/linkedlist/roots" + } } } - } - }, - "version": 1 - } - """# + }, + "version": 1 + } + """# let configuration = try decoder.decode(RegistryConfiguration.self, from: json) diff --git a/Tests/PackageRegistryTests/RegistryDownloadsManagerTests.swift b/Tests/PackageRegistryTests/RegistryDownloadsManagerTests.swift index 7da84e7b493..fa3091be584 100644 --- a/Tests/PackageRegistryTests/RegistryDownloadsManagerTests.swift +++ b/Tests/PackageRegistryTests/RegistryDownloadsManagerTests.swift @@ -49,7 +49,7 @@ final class RegistryDownloadsManagerTests: XCTestCase { let manager = RegistryDownloadsManager( fileSystem: fs, path: downloadsPath, - cachePath: .none, // cache disabled + cachePath: .none, // cache disabled registryClient: registry.registryClient, delegate: delegate ) @@ -85,17 +85,19 @@ final class RegistryDownloadsManagerTests: XCTestCase { } try delegate.wait(timeout: .now() + 2) - XCTAssertEqual(delegate.willFetch.map { ($0.packageVersion) }, - [ - (PackageVersion(package: package, version: packageVersion)), - (PackageVersion(package: unknownPackage, version: unknownPackageVersion)) - ] + XCTAssertEqual( + delegate.willFetch.map { ($0.packageVersion) }, + [ + (PackageVersion(package: package, version: packageVersion)), + (PackageVersion(package: unknownPackage, version: unknownPackageVersion)), + ] ) - XCTAssertEqual(delegate.didFetch.map { ($0.packageVersion) }, - [ - (PackageVersion(package: package, version: packageVersion)), - (PackageVersion(package: unknownPackage, version: unknownPackageVersion)) - ] + XCTAssertEqual( + delegate.didFetch.map { ($0.packageVersion) }, + [ + (PackageVersion(package: package, version: packageVersion)), + (PackageVersion(package: unknownPackage, version: unknownPackageVersion)), + ] ) } @@ -109,17 +111,19 @@ final class RegistryDownloadsManagerTests: XCTestCase { XCTAssertTrue(fs.isDirectory(path)) try delegate.wait(timeout: .now() + 2) - XCTAssertEqual(delegate.willFetch.map { ($0.packageVersion) }, - [ - (PackageVersion(package: package, version: packageVersion)), - (PackageVersion(package: unknownPackage, version: unknownPackageVersion)) - ] + XCTAssertEqual( + delegate.willFetch.map { ($0.packageVersion) }, + [ + (PackageVersion(package: package, version: packageVersion)), + (PackageVersion(package: unknownPackage, version: unknownPackageVersion)), + ] ) - XCTAssertEqual(delegate.didFetch.map { ($0.packageVersion) }, - [ - (PackageVersion(package: package, version: packageVersion)), - (PackageVersion(package: unknownPackage, version: unknownPackageVersion)) - ] + XCTAssertEqual( + delegate.didFetch.map { ($0.packageVersion) }, + [ + (PackageVersion(package: package, version: packageVersion)), + (PackageVersion(package: unknownPackage, version: unknownPackageVersion)), + ] ) } @@ -135,19 +139,21 @@ final class RegistryDownloadsManagerTests: XCTestCase { XCTAssertTrue(fs.isDirectory(path)) try delegate.wait(timeout: .now() + 2) - XCTAssertEqual(delegate.willFetch.map { ($0.packageVersion) }, - [ - (PackageVersion(package: package, version: packageVersion)), - (PackageVersion(package: unknownPackage, version: unknownPackageVersion)), - (PackageVersion(package: package, version: packageVersion)) - ] + XCTAssertEqual( + delegate.willFetch.map { ($0.packageVersion) }, + [ + (PackageVersion(package: package, version: packageVersion)), + (PackageVersion(package: unknownPackage, version: unknownPackageVersion)), + (PackageVersion(package: package, version: packageVersion)), + ] ) - XCTAssertEqual(delegate.didFetch.map { ($0.packageVersion) }, - [ - (PackageVersion(package: package, version: packageVersion)), - (PackageVersion(package: unknownPackage, version: unknownPackageVersion)), - (PackageVersion(package: package, version: packageVersion)) - ] + XCTAssertEqual( + delegate.didFetch.map { ($0.packageVersion) }, + [ + (PackageVersion(package: package, version: packageVersion)), + (PackageVersion(package: unknownPackage, version: unknownPackageVersion)), + (PackageVersion(package: package, version: packageVersion)), + ] ) } } @@ -181,7 +187,7 @@ final class RegistryDownloadsManagerTests: XCTestCase { let manager = RegistryDownloadsManager( fileSystem: fs, path: downloadsPath, - cachePath: cachePath, // cache enabled + cachePath: cachePath, // cache enabled registryClient: registry.registryClient, delegate: delegate ) @@ -270,7 +276,7 @@ final class RegistryDownloadsManagerTests: XCTestCase { let manager = RegistryDownloadsManager( fileSystem: fs, path: downloadsPath, - cachePath: .none, // cache disabled + cachePath: .none, // cache disabled registryClient: registry.registryClient, delegate: delegate ) @@ -280,7 +286,7 @@ final class RegistryDownloadsManagerTests: XCTestCase { do { let concurrency = 100 let package: PackageIdentity = .plain("test.\(UUID().uuidString)") - let packageVersions = (0 ..< concurrency).map { Version($0, 0 , 0) } + let packageVersions = (0..() try await withThrowingTaskGroup(of: Void.self) { group in - for index in 0 ..< concurrency { + for index in 0..=5.5.2) - func testSignedPackage_validSignature() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) - - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry + func testSignedPackage_validSignature() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat + ) - try await withTemporaryDirectory { temporaryDirectory in - // Write test root to trust roots directory - let trustRootsDirectoryPath = temporaryDirectory.appending(component: "trust-roots") - try localFileSystem.createDirectory(trustRootsDirectoryPath) - try localFileSystem.writeFileContents( - trustRootsDirectoryPath.appending(component: "test-root.cer"), - bytes: .init(keyAndCertChain.rootCertificate) + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry + + try await withTemporaryDirectory { temporaryDirectory in + // Write test root to trust roots directory + let trustRootsDirectoryPath = temporaryDirectory.appending(component: "trust-roots") + try localFileSystem.createDirectory(trustRootsDirectoryPath) + try localFileSystem.writeFileContents( + trustRootsDirectoryPath.appending(component: "test-root.cer"), + bytes: .init(keyAndCertChain.rootCertificate) + ) - var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.trustedRootCertificatesPath = trustRootsDirectoryPath.pathString - signingConfiguration.includeDefaultTrustedRootCertificates = false - var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() - validationChecks.certificateExpiration = .disabled - validationChecks.certificateRevocation = .disabled - signingConfiguration.validationChecks = validationChecks + var signingConfiguration = RegistryConfiguration.Security.Signing() + signingConfiguration.trustedRootCertificatesPath = trustRootsDirectoryPath.pathString + signingConfiguration.includeDefaultTrustedRootCertificates = false + var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() + validationChecks.certificateExpiration = .disabled + validationChecks.certificateRevocation = .disabled + signingConfiguration.validationChecks = validationChecks + + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: signingConfiguration + ) + ) + + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode + ) + + let signatureValidation = SignatureValidation( + skipSignatureValidation: false, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: RejectingSignatureValidationDelegate() + ) + + // Package signature is valid + _ = try await signatureValidation.validate( + registry: registry, + package: package, + version: version, + content: Data(emptyZipFile.contents), + configuration: configuration.signing(for: package, registry: registry) + ) + } + } + + func testSignedPackage_badSignature() async throws { + let signatureBytes = Array("bad signature".utf8) + let signatureFormat = SignatureFormat.cms_1_0_0 + + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry configuration.security = RegistryConfiguration.Security( default: RegistryConfiguration.Security.Global( - signing: signingConfiguration + signing: .init() ) ) - - let registryClient = makeRegistryClient( configuration: configuration, httpClient: httpClient, @@ -743,149 +779,173 @@ final class SignatureValidationTests: XCTestCase { delegate: RejectingSignatureValidationDelegate() ) - // Package signature is valid - _ = try await signatureValidation.validate( - registry: registry, - package: package, - version: version, - content: Data(emptyZipFile.contents), - configuration: configuration.signing(for: package, registry: registry) - ) + // Package signature can't be parsed so it is invalid + await XCTAssertAsyncThrowsError( + try await signatureValidation.validate( + registry: registry, + package: package, + version: version, + content: Data(emptyZipFile.contents), + configuration: configuration.signing(for: package, registry: registry) + ) + ) { error in + guard case RegistryError.invalidSignature = error else { + return XCTFail("Expected RegistryError.invalidSignature, got '\(error)'") + } + } } - } - func testSignedPackage_badSignature() async throws { - let signatureBytes = Array("bad signature".utf8) - let signatureFormat = SignatureFormat.cms_1_0_0 + func testSignedPackage_badSignature_skipSignatureValidation() async throws { + // Get metadata endpoint will be called to see if package version is signed + let handler: HTTPClient.Implementation = { _, _ in + throw StringError("unexpected request") + } - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: .init() + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: .init() + ) ) - ) + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode + ) - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) - - let signatureValidation = SignatureValidation( - skipSignatureValidation: false, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() - ) + let signatureValidation = SignatureValidation( + skipSignatureValidation: true, // intended for this test, don't change + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: RejectingSignatureValidationDelegate() + ) - // Package signature can't be parsed so it is invalid - await XCTAssertAsyncThrowsError( - try await signatureValidation.validate( + // Signature is bad, but we are skipping signature + // validation, so no error is thrown. + _ = try await signatureValidation.validate( registry: registry, package: package, version: version, content: Data(emptyZipFile.contents), configuration: configuration.signing(for: package, registry: registry) ) - ) { error in - guard case RegistryError.invalidSignature = error else { - return XCTFail("Expected RegistryError.invalidSignature, got '\(error)'") - } } - } - - func testSignedPackage_badSignature_skipSignatureValidation() async throws { - // Get metadata endpoint will be called to see if package version is signed - let handler: HTTPClient.Implementation = { _, _ in - throw StringError("unexpected request") - } - - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: .init() + func testSignedPackage_invalidSignature() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: Array("other zip archive".utf8), // signature is not for emptyZipFile but for something else + signingIdentity: signingIdentity, + format: signatureFormat ) - ) + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry + + try await withTemporaryDirectory { temporaryDirectory in + // Write test root to trust roots directory + let trustRootsDirectoryPath = temporaryDirectory.appending(component: "trust-roots") + try localFileSystem.createDirectory(trustRootsDirectoryPath) + try localFileSystem.writeFileContents( + trustRootsDirectoryPath.appending(component: "test-root.cer"), + bytes: .init(keyAndCertChain.rootCertificate) + ) - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) + var signingConfiguration = RegistryConfiguration.Security.Signing() + signingConfiguration.trustedRootCertificatesPath = trustRootsDirectoryPath.pathString + signingConfiguration.includeDefaultTrustedRootCertificates = false + var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() + validationChecks.certificateExpiration = .disabled + validationChecks.certificateRevocation = .disabled + signingConfiguration.validationChecks = validationChecks + + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: signingConfiguration + ) + ) - let signatureValidation = SignatureValidation( - skipSignatureValidation: true, // intended for this test, don't change - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() - ) + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode + ) - // Signature is bad, but we are skipping signature - // validation, so no error is thrown. - _ = try await signatureValidation.validate( - registry: registry, - package: package, - version: version, - content: Data(emptyZipFile.contents), - configuration: configuration.signing(for: package, registry: registry) - ) - } + let signatureValidation = SignatureValidation( + skipSignatureValidation: false, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: RejectingSignatureValidationDelegate() + ) - func testSignedPackage_invalidSignature() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: Array("other zip archive".utf8), // signature is not for emptyZipFile but for something else - signingIdentity: signingIdentity, - format: signatureFormat - ) + // Package signature doesn't match content so it's invalid + await XCTAssertAsyncThrowsError( + try await signatureValidation.validate( + registry: registry, + package: package, + version: version, + content: Data(emptyZipFile.contents), + configuration: configuration.signing(for: package, registry: registry) + ) + ) { error in + guard case RegistryError.invalidSignature = error else { + return XCTFail("Expected RegistryError.invalidSignature, got '\(error)'") + } + } + } + } - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry + func testSignedPackage_certificateNotTrusted_shouldError() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat + ) - try await withTemporaryDirectory { temporaryDirectory in - // Write test root to trust roots directory - let trustRootsDirectoryPath = temporaryDirectory.appending(component: "trust-roots") - try localFileSystem.createDirectory(trustRootsDirectoryPath) - try localFileSystem.writeFileContents( - trustRootsDirectoryPath.appending(component: "test-root.cer"), - bytes: .init(keyAndCertChain.rootCertificate) + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat ) + let httpClient = HTTPClient(implementation: handler) + + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.trustedRootCertificatesPath = trustRootsDirectoryPath.pathString + signingConfiguration.onUntrustedCertificate = .error // intended for this test; don't change + // Test root not written to trust roots directory signingConfiguration.includeDefaultTrustedRootCertificates = false var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() validationChecks.certificateExpiration = .disabled @@ -898,8 +958,6 @@ final class SignatureValidationTests: XCTestCase { ) ) - - let registryClient = makeRegistryClient( configuration: configuration, httpClient: httpClient, @@ -915,7 +973,7 @@ final class SignatureValidationTests: XCTestCase { delegate: RejectingSignatureValidationDelegate() ) - // Package signature doesn't match content so it's invalid + // Test root not trusted; onUntrustedCertificate is set to .error await XCTAssertAsyncThrowsError( try await signatureValidation.validate( registry: registry, @@ -925,302 +983,135 @@ final class SignatureValidationTests: XCTestCase { configuration: configuration.signing(for: package, registry: registry) ) ) { error in - guard case RegistryError.invalidSignature = error else { - return XCTFail("Expected RegistryError.invalidSignature, got '\(error)'") + guard case RegistryError.signerNotTrusted = error else { + return XCTFail("Expected RegistryError.signerNotTrusted, got '\(error)'") } } } - } - func testSignedPackage_certificateNotTrusted_shouldError() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) + func testSignedPackage_certificateNotTrusted_shouldPrompt() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat + ) - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry + var signingConfiguration = RegistryConfiguration.Security.Signing() + signingConfiguration.onUntrustedCertificate = .prompt // intended for this test; don't change + // Test root not written to trust roots directory + signingConfiguration.includeDefaultTrustedRootCertificates = false + var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() + validationChecks.certificateExpiration = .disabled + validationChecks.certificateRevocation = .disabled + signingConfiguration.validationChecks = validationChecks - var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.onUntrustedCertificate = .error // intended for this test; don't change - // Test root not written to trust roots directory - signingConfiguration.includeDefaultTrustedRootCertificates = false - var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() - validationChecks.certificateExpiration = .disabled - validationChecks.certificateRevocation = .disabled - signingConfiguration.validationChecks = validationChecks + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: signingConfiguration + ) + ) - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: signingConfiguration + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode ) - ) + // prompt returning false + do { + let signatureValidation = SignatureValidation( + skipSignatureValidation: false, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: RejectingSignatureValidationDelegate() + ) - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) - - let signatureValidation = SignatureValidation( - skipSignatureValidation: false, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() - ) - - // Test root not trusted; onUntrustedCertificate is set to .error - await XCTAssertAsyncThrowsError( - try await signatureValidation.validate( - registry: registry, - package: package, - version: version, - content: Data(emptyZipFile.contents), - configuration: configuration.signing(for: package, registry: registry) - ) - ) { error in - guard case RegistryError.signerNotTrusted = error else { - return XCTFail("Expected RegistryError.signerNotTrusted, got '\(error)'") + // Test root not trusted; onUntrustedCertificate is set to .prompt + await XCTAssertAsyncThrowsError( + try await signatureValidation.validate( + registry: registry, + package: package, + version: version, + content: Data(emptyZipFile.contents), + configuration: configuration.signing(for: package, registry: registry) + ) + ) { error in + guard case RegistryError.signerNotTrusted = error else { + return XCTFail("Expected RegistryError.signerNotTrusted, got '\(error)'") + } + } } - } - } - - func testSignedPackage_certificateNotTrusted_shouldPrompt() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) - - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry - - var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.onUntrustedCertificate = .prompt // intended for this test; don't change - // Test root not written to trust roots directory - signingConfiguration.includeDefaultTrustedRootCertificates = false - var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() - validationChecks.certificateExpiration = .disabled - validationChecks.certificateRevocation = .disabled - signingConfiguration.validationChecks = validationChecks - - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: signingConfiguration - ) - ) - - - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) - // prompt returning false - do { - let signatureValidation = SignatureValidation( - skipSignatureValidation: false, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() - ) + // prompt returning continue + do { + let signatureValidation = SignatureValidation( + skipSignatureValidation: false, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: AcceptingSignatureValidationDelegate() + ) - // Test root not trusted; onUntrustedCertificate is set to .prompt - await XCTAssertAsyncThrowsError( - try await signatureValidation.validate( + // Package signer is untrusted, signingEntity should be nil + let signingEntity = try await signatureValidation.validate( registry: registry, package: package, version: version, content: Data(emptyZipFile.contents), configuration: configuration.signing(for: package, registry: registry) ) - ) { error in - guard case RegistryError.signerNotTrusted = error else { - return XCTFail("Expected RegistryError.signerNotTrusted, got '\(error)'") - } + XCTAssertNil(signingEntity) } } - // prompt returning continue - do { - let signatureValidation = SignatureValidation( - skipSignatureValidation: false, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: AcceptingSignatureValidationDelegate() + func testSignedPackage_certificateNotTrusted_shouldWarn() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 ) - - // Package signer is untrusted, signingEntity should be nil - let signingEntity = try await signatureValidation.validate( - registry: registry, - package: package, - version: version, - content: Data(emptyZipFile.contents), - configuration: configuration.signing(for: package, registry: registry) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat ) - XCTAssertNil(signingEntity) - } - } - func testSignedPackage_certificateNotTrusted_shouldWarn() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) - - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry - - var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.onUntrustedCertificate = .warn // intended for this test; don't change - // Test root not written to trust roots directory - signingConfiguration.includeDefaultTrustedRootCertificates = false - var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() - validationChecks.certificateExpiration = .disabled - validationChecks.certificateRevocation = .disabled - signingConfiguration.validationChecks = validationChecks - - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: signingConfiguration - ) - ) - - - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) - - let signatureValidation = SignatureValidation( - skipSignatureValidation: false, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() - ) - - let observability = ObservabilitySystem.makeForTesting() - - // Test root not trusted but onUntrustedCertificate is set to .warn - _ = try await signatureValidation.validate( - registry: registry, - package: package, - version: version, - content: Data(emptyZipFile.contents), - configuration: configuration.signing(for: package, registry: registry), - observabilityScope: observability.topScope - ) - - testDiagnostics(observability.diagnostics) { result in - let diagnostics = result.check(diagnostic: .contains("not trusted"), severity: .warning) - XCTAssertEqual(diagnostics?.metadata?.packageIdentity, package.underlying) - } - } - - func testSignedManifest_validSignature() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) - - let manifestSignatureBytes = try self.sign( - content: Array(Self.unsignedManifest.utf8), - signingIdentity: signingIdentity, - format: signatureFormat - ) - let manifestContent = """ - \(Self.unsignedManifest) - // signature: cms-1.0.0;\(Data(manifestSignatureBytes).base64EncodedString()) - """ - - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry - - try await withTemporaryDirectory { temporaryDirectory in - // Write test root to trust roots directory - let trustRootsDirectoryPath = temporaryDirectory.appending(component: "trust-roots") - try localFileSystem.createDirectory(trustRootsDirectoryPath) - try localFileSystem.writeFileContents( - trustRootsDirectoryPath.appending(component: "test-root.cer"), - bytes: .init(keyAndCertChain.rootCertificate) + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.trustedRootCertificatesPath = trustRootsDirectoryPath.pathString + signingConfiguration.onUntrustedCertificate = .warn // intended for this test; don't change + // Test root not written to trust roots directory signingConfiguration.includeDefaultTrustedRootCertificates = false var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() validationChecks.certificateExpiration = .disabled @@ -1233,8 +1124,6 @@ final class SignatureValidationTests: XCTestCase { ) ) - - let registryClient = makeRegistryClient( configuration: configuration, httpClient: httpClient, @@ -1250,210 +1139,145 @@ final class SignatureValidationTests: XCTestCase { delegate: RejectingSignatureValidationDelegate() ) - // Manifest signature is valid + let observability = ObservabilitySystem.makeForTesting() + + // Test root not trusted but onUntrustedCertificate is set to .warn _ = try await signatureValidation.validate( registry: registry, package: package, version: version, - toolsVersion: .none, - manifestContent: manifestContent, - configuration: configuration.signing(for: package, registry: registry) - ) - } - } - - func testSignedManifest_badSignature() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) - - let manifestContent = """ - \(Self.unsignedManifest) - // signature: cms-1.0.0;\(Data(Array("bad signature".utf8)).base64EncodedString()) - """ - - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry - - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: .init() + content: Data(emptyZipFile.contents), + configuration: configuration.signing(for: package, registry: registry), + observabilityScope: observability.topScope ) - ) - - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) - - let signatureValidation = SignatureValidation( - skipSignatureValidation: false, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() - ) - // Manifest signature can't be parsed so it is invalid - await XCTAssertAsyncThrowsError( - try await signatureValidation.validate( - registry: registry, - package: package, - version: version, - toolsVersion: .none, - manifestContent: manifestContent, - configuration: configuration.signing(for: package, registry: registry) - ) - ) { error in - guard case RegistryError.invalidSignature = error else { - return XCTFail("Expected RegistryError.invalidSignature, got '\(error)'") + testDiagnostics(observability.diagnostics) { result in + let diagnostics = result.check(diagnostic: .contains("not trusted"), severity: .warning) + XCTAssertEqual(diagnostics?.metadata?.packageIdentity, package.underlying) } } - } - - func testSignedManifest_badSignature_skipSignatureValidation() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) - let manifestContent = """ - \(Self.unsignedManifest) - // signature: cms-1.0.0;\(Data(Array("bad signature".utf8)).base64EncodedString()) - """ - - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry - - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: .init() + func testSignedManifest_validSignature() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat ) - ) - - - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) - let signatureValidation = SignatureValidation( - skipSignatureValidation: true, // intended for this test, don't change - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() - ) + let manifestSignatureBytes = try self.sign( + content: Array(Self.unsignedManifest.utf8), + signingIdentity: signingIdentity, + format: signatureFormat + ) + let manifestContent = """ + \(Self.unsignedManifest) + // signature: cms-1.0.0;\(Data(manifestSignatureBytes).base64EncodedString()) + """ + + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry + + try await withTemporaryDirectory { temporaryDirectory in + // Write test root to trust roots directory + let trustRootsDirectoryPath = temporaryDirectory.appending(component: "trust-roots") + try localFileSystem.createDirectory(trustRootsDirectoryPath) + try localFileSystem.writeFileContents( + trustRootsDirectoryPath.appending(component: "test-root.cer"), + bytes: .init(keyAndCertChain.rootCertificate) + ) - // Manifest signature is bad, but we are skipping signature - // validation, so no error is thrown. - _ = try await signatureValidation.validate( - registry: registry, - package: package, - version: version, - toolsVersion: .none, - manifestContent: manifestContent, - configuration: configuration.signing(for: package, registry: registry) - ) - } + var signingConfiguration = RegistryConfiguration.Security.Signing() + signingConfiguration.trustedRootCertificatesPath = trustRootsDirectoryPath.pathString + signingConfiguration.includeDefaultTrustedRootCertificates = false + var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() + validationChecks.certificateExpiration = .disabled + validationChecks.certificateRevocation = .disabled + signingConfiguration.validationChecks = validationChecks + + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: signingConfiguration + ) + ) - func testSignedManifest_invalidSignature() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode + ) - let manifestSignatureBytes = try self.sign( - content: Array("not manifest".utf8), // signature is not for manifest but for something else - signingIdentity: signingIdentity, - format: signatureFormat - ) - let manifestContent = """ - \(Self.unsignedManifest) - // signature: cms-1.0.0;\(Data(manifestSignatureBytes).base64EncodedString()) - """ + let signatureValidation = SignatureValidation( + skipSignatureValidation: false, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: RejectingSignatureValidationDelegate() + ) - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry + // Manifest signature is valid + _ = try await signatureValidation.validate( + registry: registry, + package: package, + version: version, + toolsVersion: .none, + manifestContent: manifestContent, + configuration: configuration.signing(for: package, registry: registry) + ) + } + } - try await withTemporaryDirectory { temporaryDirectory in - // Write test root to trust roots directory - let trustRootsDirectoryPath = temporaryDirectory.appending(component: "trust-roots") - try localFileSystem.createDirectory(trustRootsDirectoryPath) - try localFileSystem.writeFileContents( - trustRootsDirectoryPath.appending(component: "test-root.cer"), - bytes: .init(keyAndCertChain.rootCertificate) + func testSignedManifest_badSignature() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat ) - var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.trustedRootCertificatesPath = trustRootsDirectoryPath.pathString - signingConfiguration.includeDefaultTrustedRootCertificates = false - var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() - validationChecks.certificateExpiration = .disabled - validationChecks.certificateRevocation = .disabled - signingConfiguration.validationChecks = validationChecks + let manifestContent = """ + \(Self.unsignedManifest) + // signature: cms-1.0.0;\(Data(Array("bad signature".utf8)).base64EncodedString()) + """ + + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry configuration.security = RegistryConfiguration.Security( default: RegistryConfiguration.Security.Global( - signing: signingConfiguration + signing: .init() ) ) - - let registryClient = makeRegistryClient( configuration: configuration, httpClient: httpClient, @@ -1469,7 +1293,7 @@ final class SignatureValidationTests: XCTestCase { delegate: RejectingSignatureValidationDelegate() ) - // Manifest signature doesn't match content so it's invalid + // Manifest signature can't be parsed so it is invalid await XCTAssertAsyncThrowsError( try await signatureValidation.validate( registry: registry, @@ -1485,79 +1309,257 @@ final class SignatureValidationTests: XCTestCase { } } } - } - func testSignedManifest_certificateNotTrusted_shouldPrompt() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) + func testSignedManifest_badSignature_skipSignatureValidation() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat + ) - let manifestSignatureBytes = try self.sign( - content: Array(Self.unsignedManifest.utf8), - signingIdentity: signingIdentity, - format: signatureFormat - ) - let manifestContent = """ - \(Self.unsignedManifest) - // signature: cms-1.0.0;\(Data(manifestSignatureBytes).base64EncodedString()) - """ + let manifestContent = """ + \(Self.unsignedManifest) + // signature: cms-1.0.0;\(Data(Array("bad signature".utf8)).base64EncodedString()) + """ + + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: .init() + ) + ) + + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode + ) + + let signatureValidation = SignatureValidation( + skipSignatureValidation: true, // intended for this test, don't change + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: RejectingSignatureValidationDelegate() + ) + + // Manifest signature is bad, but we are skipping signature + // validation, so no error is thrown. + _ = try await signatureValidation.validate( + registry: registry, + package: package, + version: version, + toolsVersion: .none, + manifestContent: manifestContent, + configuration: configuration.signing(for: package, registry: registry) + ) + } + + func testSignedManifest_invalidSignature() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat + ) + + let manifestSignatureBytes = try self.sign( + content: Array("not manifest".utf8), // signature is not for manifest but for something else + signingIdentity: signingIdentity, + format: signatureFormat + ) + let manifestContent = """ + \(Self.unsignedManifest) + // signature: cms-1.0.0;\(Data(manifestSignatureBytes).base64EncodedString()) + """ + + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry + + try await withTemporaryDirectory { temporaryDirectory in + // Write test root to trust roots directory + let trustRootsDirectoryPath = temporaryDirectory.appending(component: "trust-roots") + try localFileSystem.createDirectory(trustRootsDirectoryPath) + try localFileSystem.writeFileContents( + trustRootsDirectoryPath.appending(component: "test-root.cer"), + bytes: .init(keyAndCertChain.rootCertificate) + ) + + var signingConfiguration = RegistryConfiguration.Security.Signing() + signingConfiguration.trustedRootCertificatesPath = trustRootsDirectoryPath.pathString + signingConfiguration.includeDefaultTrustedRootCertificates = false + var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() + validationChecks.certificateExpiration = .disabled + validationChecks.certificateRevocation = .disabled + signingConfiguration.validationChecks = validationChecks + + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: signingConfiguration + ) + ) + + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode + ) + + let signatureValidation = SignatureValidation( + skipSignatureValidation: false, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: RejectingSignatureValidationDelegate() + ) - var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.onUntrustedCertificate = .prompt // intended for this test; don't change - // Test root not written to trust roots directory - signingConfiguration.includeDefaultTrustedRootCertificates = false - var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() - validationChecks.certificateExpiration = .disabled - validationChecks.certificateRevocation = .disabled - signingConfiguration.validationChecks = validationChecks + // Manifest signature doesn't match content so it's invalid + await XCTAssertAsyncThrowsError( + try await signatureValidation.validate( + registry: registry, + package: package, + version: version, + toolsVersion: .none, + manifestContent: manifestContent, + configuration: configuration.signing(for: package, registry: registry) + ) + ) { error in + guard case RegistryError.invalidSignature = error else { + return XCTFail("Expected RegistryError.invalidSignature, got '\(error)'") + } + } + } + } - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: signingConfiguration + func testSignedManifest_certificateNotTrusted_shouldPrompt() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat ) - ) + let manifestSignatureBytes = try self.sign( + content: Array(Self.unsignedManifest.utf8), + signingIdentity: signingIdentity, + format: signatureFormat + ) + let manifestContent = """ + \(Self.unsignedManifest) + // signature: cms-1.0.0;\(Data(manifestSignatureBytes).base64EncodedString()) + """ + + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) + var signingConfiguration = RegistryConfiguration.Security.Signing() + signingConfiguration.onUntrustedCertificate = .prompt // intended for this test; don't change + // Test root not written to trust roots directory + signingConfiguration.includeDefaultTrustedRootCertificates = false + var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() + validationChecks.certificateExpiration = .disabled + validationChecks.certificateRevocation = .disabled + signingConfiguration.validationChecks = validationChecks - // prompt returning false - do { - let signatureValidation = SignatureValidation( - skipSignatureValidation: false, + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: signingConfiguration + ) + ) + + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() + signingEntityCheckingMode: signingEntityCheckingMode ) - // Test root not trusted; onUntrustedCertificate is set to .prompt - await XCTAssertAsyncThrowsError( - try await signatureValidation.validate( + // prompt returning false + do { + let signatureValidation = SignatureValidation( + skipSignatureValidation: false, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: RejectingSignatureValidationDelegate() + ) + + // Test root not trusted; onUntrustedCertificate is set to .prompt + await XCTAssertAsyncThrowsError( + try await signatureValidation.validate( + registry: registry, + package: package, + version: version, + toolsVersion: .none, + manifestContent: manifestContent, + configuration: configuration.signing(for: package, registry: registry) + ) + ) { error in + guard case RegistryError.signerNotTrusted = error else { + return XCTFail("Expected RegistryError.signerNotTrusted, got '\(error)'") + } + } + } + + // prompt returning continue + do { + let signatureValidation = SignatureValidation( + skipSignatureValidation: false, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: AcceptingSignatureValidationDelegate() + ) + + // Package signer is not trusted, signingEntity should be nil + let signingEntity = try await signatureValidation.validate( registry: registry, package: package, version: version, @@ -1565,196 +1567,168 @@ final class SignatureValidationTests: XCTestCase { manifestContent: manifestContent, configuration: configuration.signing(for: package, registry: registry) ) - ) { error in - guard case RegistryError.signerNotTrusted = error else { - return XCTFail("Expected RegistryError.signerNotTrusted, got '\(error)'") - } + XCTAssertNil(signingEntity) } } - // prompt returning continue - do { + func testSignedManifest_certificateNotTrusted_nonPrompt() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat + ) + + let manifestSignatureBytes = try self.sign( + content: Array(Self.unsignedManifest.utf8), + signingIdentity: signingIdentity, + format: signatureFormat + ) + let manifestContent = """ + \(Self.unsignedManifest) + // signature: cms-1.0.0;\(Data(manifestSignatureBytes).base64EncodedString()) + """ + + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry + + var signingConfiguration = RegistryConfiguration.Security.Signing() + signingConfiguration.onUntrustedCertificate = .error // intended for this test; don't change + // Test root not written to trust roots directory + signingConfiguration.includeDefaultTrustedRootCertificates = false + var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() + validationChecks.certificateExpiration = .disabled + validationChecks.certificateRevocation = .disabled + signingConfiguration.validationChecks = validationChecks + + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: signingConfiguration + ) + ) + + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode + ) + let signatureValidation = SignatureValidation( skipSignatureValidation: false, signingEntityStorage: signingEntityStorage, signingEntityCheckingMode: signingEntityCheckingMode, versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: AcceptingSignatureValidationDelegate() + delegate: RejectingSignatureValidationDelegate() ) - // Package signer is not trusted, signingEntity should be nil - let signingEntity = try await signatureValidation.validate( + let observability = ObservabilitySystem.makeForTesting() + + // Test root not trusted. + // With the exception of .prompt, we log then continue. + _ = try await signatureValidation.validate( registry: registry, package: package, version: version, toolsVersion: .none, manifestContent: manifestContent, - configuration: configuration.signing(for: package, registry: registry) - ) - XCTAssertNil(signingEntity) - } - } - - func testSignedManifest_certificateNotTrusted_nonPrompt() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) - - let manifestSignatureBytes = try self.sign( - content: Array(Self.unsignedManifest.utf8), - signingIdentity: signingIdentity, - format: signatureFormat - ) - let manifestContent = """ - \(Self.unsignedManifest) - // signature: cms-1.0.0;\(Data(manifestSignatureBytes).base64EncodedString()) - """ - - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry - - var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.onUntrustedCertificate = .error // intended for this test; don't change - // Test root not written to trust roots directory - signingConfiguration.includeDefaultTrustedRootCertificates = false - var validationChecks = RegistryConfiguration.Security.Signing.ValidationChecks() - validationChecks.certificateExpiration = .disabled - validationChecks.certificateRevocation = .disabled - signingConfiguration.validationChecks = validationChecks - - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: signingConfiguration + configuration: configuration.signing(for: package, registry: registry), + observabilityScope: observability.topScope ) - ) - - - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) - - let signatureValidation = SignatureValidation( - skipSignatureValidation: false, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() - ) - - let observability = ObservabilitySystem.makeForTesting() - - // Test root not trusted. - // With the exception of .prompt, we log then continue. - _ = try await signatureValidation.validate( - registry: registry, - package: package, - version: version, - toolsVersion: .none, - manifestContent: manifestContent, - configuration: configuration.signing(for: package, registry: registry), - observabilityScope: observability.topScope - ) - testDiagnostics(observability.diagnostics, problemsOnly: false) { result in - let diagnostics = result.check(diagnostic: .contains("not trusted"), severity: .debug) - XCTAssertEqual(diagnostics?.metadata?.packageIdentity, package.underlying) + testDiagnostics(observability.diagnostics, problemsOnly: false) { result in + let diagnostics = result.check(diagnostic: .contains("not trusted"), severity: .debug) + XCTAssertEqual(diagnostics?.metadata?.packageIdentity, package.underlying) + } } - } - - func testSignedManifest_emptyResources() async throws { - let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() - let signingIdentity = try SwiftSigningIdentity( - derEncodedCertificate: keyAndCertChain.leafCertificate, - derEncodedPrivateKey: keyAndCertChain.privateKey, - privateKeyType: .p256 - ) - let signatureFormat = SignatureFormat.cms_1_0_0 - let signatureBytes = try self.sign( - content: emptyZipFile.contents, - signingIdentity: signingIdentity, - format: signatureFormat - ) - - // Get metadata endpoint will be called to see if package version is signed - let handler = HTTPClient.packageReleaseMetadataAPIHandler( - metadataURL: metadataURL, - checksum: checksum, - signatureBytes: signatureBytes, - signatureFormat: signatureFormat, - includeResouces: false - ) - let httpClient = HTTPClient(implementation: handler) - var configuration = RegistryConfiguration() - configuration.defaultRegistry = registry - var signingConfiguration = RegistryConfiguration.Security.Signing() - signingConfiguration.onUnsigned = .error // intended for this test; don't change - configuration.security = RegistryConfiguration.Security( - default: RegistryConfiguration.Security.Global( - signing: signingConfiguration + func testSignedManifest_emptyResources() async throws { + let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() + let signingIdentity = try SwiftSigningIdentity( + derEncodedCertificate: keyAndCertChain.leafCertificate, + derEncodedPrivateKey: keyAndCertChain.privateKey, + privateKeyType: .p256 + ) + let signatureFormat = SignatureFormat.cms_1_0_0 + let signatureBytes = try self.sign( + content: emptyZipFile.contents, + signingIdentity: signingIdentity, + format: signatureFormat ) - ) + // Get metadata endpoint will be called to see if package version is signed + let handler = HTTPClient.packageReleaseMetadataAPIHandler( + metadataURL: metadataURL, + checksum: checksum, + signatureBytes: signatureBytes, + signatureFormat: signatureFormat, + includeResouces: false + ) + let httpClient = HTTPClient(implementation: handler) + var configuration = RegistryConfiguration() + configuration.defaultRegistry = registry - let registryClient = makeRegistryClient( - configuration: configuration, - httpClient: httpClient, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode - ) + var signingConfiguration = RegistryConfiguration.Security.Signing() + signingConfiguration.onUnsigned = .error // intended for this test; don't change + configuration.security = RegistryConfiguration.Security( + default: RegistryConfiguration.Security.Global( + signing: signingConfiguration + ) + ) - let signatureValidation = SignatureValidation( - skipSignatureValidation: false, - signingEntityStorage: signingEntityStorage, - signingEntityCheckingMode: signingEntityCheckingMode, - versionMetadataProvider: registryClient.getPackageVersionMetadata, - delegate: RejectingSignatureValidationDelegate() - ) + let registryClient = makeRegistryClient( + configuration: configuration, + httpClient: httpClient, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode + ) - let observability = ObservabilitySystem.makeForTesting() + let signatureValidation = SignatureValidation( + skipSignatureValidation: false, + signingEntityStorage: signingEntityStorage, + signingEntityCheckingMode: signingEntityCheckingMode, + versionMetadataProvider: registryClient.getPackageVersionMetadata, + delegate: RejectingSignatureValidationDelegate() + ) - // Archive is signed, but manifest is not signed - let entity = try await signatureValidation.validate( - registry: registry, - package: package, - version: version, - toolsVersion: ToolsVersion.v5_7, - manifestContent: Self.unsignedManifest, - configuration: configuration.signing(for: package, registry: registry), - observabilityScope: observability.topScope - ) - XCTAssertNil(entity, "Expected no signing entity") + let observability = ObservabilitySystem.makeForTesting() - let manifestName = "Package@swift-\(ToolsVersion.v5_7).swift" - testDiagnostics(observability.diagnostics, problemsOnly: false) { result in - result.check( - diagnostic: .contains( - "cannot determine if \(manifestName) should be signed because source archive for \(package!) \(version) is not found in \(registry!)" - ), - severity: .debug + // Archive is signed, but manifest is not signed + let entity = try await signatureValidation.validate( + registry: registry, + package: package, + version: version, + toolsVersion: ToolsVersion.v5_7, + manifestContent: Self.unsignedManifest, + configuration: configuration.signing(for: package, registry: registry), + observabilityScope: observability.topScope ) + XCTAssertNil(entity, "Expected no signing entity") + + let manifestName = "Package@swift-\(ToolsVersion.v5_7).swift" + testDiagnostics(observability.diagnostics, problemsOnly: false) { result in + result.check( + diagnostic: .contains( + "cannot determine if \(manifestName) should be signed because source archive for \(package!) \(version) is not found in \(registry!)" + ), + severity: .debug + ) + } } - } #endif private func sign( @@ -1914,21 +1888,21 @@ extension HTTPClient { XCTAssertEqual(request.headers.get("Accept").first, "application/vnd.swift.registry.v1+json") let data = """ - { - "id": "mona.LinkedList", - "version": "1.1.1", - "resources": [ - { - "name": "source-archive", - "type": "application/zip", - "checksum": "\(checksum)" + { + "id": "mona.LinkedList", + "version": "1.1.1", + "resources": [ + { + "name": "source-archive", + "type": "application/zip", + "checksum": "\(checksum)" + } + ], + "metadata": { + "description": "One thing links to another." } - ], - "metadata": { - "description": "One thing links to another." } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, @@ -1958,11 +1932,11 @@ extension HTTPClient { XCTAssertEqual(request.headers.get("Accept").first, "application/vnd.swift.registry.v1+json") let data = """ - { - "id": "mona.LinkedList", - "version": "1.1.1", - "resources": [ - \(includeResouces ? """ + { + "id": "mona.LinkedList", + "version": "1.1.1", + "resources": [ + \(includeResouces ? """ { "name": "source-archive", "type": "application/zip", @@ -1973,12 +1947,12 @@ extension HTTPClient { } } """ : "") - ], - "metadata": { - "description": "One thing links to another." + ], + "metadata": { + "description": "One thing links to another." + } } - } - """.data(using: .utf8)! + """.data(using: .utf8)! return .init( statusCode: 200, diff --git a/Tests/PackageSigningTests/FilePackageSigningEntityStorageTests.swift b/Tests/PackageSigningTests/FilePackageSigningEntityStorageTests.swift index 8f8db5838d1..d62f8168224 100644 --- a/Tests/PackageSigningTests/FilePackageSigningEntityStorageTests.swift +++ b/Tests/PackageSigningTests/FilePackageSigningEntityStorageTests.swift @@ -70,8 +70,10 @@ struct FilePackageSigningEntityStorageTests { // A data file should have been created for each package #expect(mockFileSystem.exists(storage.directoryPath.appending(component: package.signedVersionsFilename))) - #expect(mockFileSystem - .exists(storage.directoryPath.appending(component: otherPackage.signedVersionsFilename))) + #expect( + mockFileSystem + .exists(storage.directoryPath.appending(component: otherPackage.signedVersionsFilename)) + ) // Signed versions should be saved do { @@ -163,7 +165,7 @@ struct FilePackageSigningEntityStorageTests { package: package, version: version, signingEntity: appleseed, - origin: .registry(URL("http://bar.com")) // origin is different and should be added + origin: .registry(URL("http://bar.com")) // origin is different and should be added ) let packageSigners = try storage.get(package: package) @@ -188,7 +190,7 @@ struct FilePackageSigningEntityStorageTests { package: package, version: version, signingEntity: appleseed, - origin: .registry(URL("http://bar.com")) // origin is different and should be added + origin: .registry(URL("http://bar.com")) // origin is different and should be added ) } throws: { error in guard case PackageSigningEntityStorageError.unrecognizedSigningEntity = error else { diff --git a/Tests/PackageSigningTests/SigningEntityTests.swift b/Tests/PackageSigningTests/SigningEntityTests.swift index 46ae6a98701..e87736326dd 100644 --- a/Tests/PackageSigningTests/SigningEntityTests.swift +++ b/Tests/PackageSigningTests/SigningEntityTests.swift @@ -39,7 +39,7 @@ struct SigningEntityTests { organizationalUnit: "SwiftPM Test Unit Y", organization: "C" ) - #expect(adp1 == adp2) // Only team ID (org unit) needs to match + #expect(adp1 == adp2) // Only team ID (org unit) needs to match #expect(adp1 != adp3) } @@ -47,7 +47,7 @@ struct SigningEntityTests { "From certificate key", arguments: [ (certificateFilename: "Test_ec.cer", id: "EC Key"), - (certificateFilename: "Test_rsa.cer", id: "RSA Key") + (certificateFilename: "Test_rsa.cer", id: "RSA Key"), ] ) func fromCertificate(certificateFilename: String, id: String) throws { @@ -73,31 +73,31 @@ struct SigningEntityTests { final class SigningEntityXCTests: XCTestCase { #if os(macOS) - func testFromKeychainCertificate() async throws { - #if ENABLE_REAL_SIGNING_IDENTITY_TEST - #else - try XCTSkipIf(true) - #endif + func testFromKeychainCertificate() async throws { + #if ENABLE_REAL_SIGNING_IDENTITY_TEST + #else + try XCTSkipIf(true) + #endif - guard let label = Environment.current["REAL_SIGNING_IDENTITY_LABEL"] else { - throw XCTSkip("Skipping because 'REAL_SIGNING_IDENTITY_LABEL' env var is not set") - } - let identityStore = SigningIdentityStore(observabilityScope: ObservabilitySystem.NOOP) - let matches = identityStore.find(by: label) - XCTAssertTrue(!matches.isEmpty) + guard let label = Environment.current["REAL_SIGNING_IDENTITY_LABEL"] else { + throw XCTSkip("Skipping because 'REAL_SIGNING_IDENTITY_LABEL' env var is not set") + } + let identityStore = SigningIdentityStore(observabilityScope: ObservabilitySystem.NOOP) + let matches = identityStore.find(by: label) + XCTAssertTrue(!matches.isEmpty) - let certificate = try Certificate(secIdentity: matches[0] as! SecIdentity) - let signingEntity = SigningEntity.from(certificate: certificate) - switch signingEntity { - case .recognized(_, let name, let organizationalUnit, let organization): - XCTAssertEqual(name, certificate.subject.commonName) - XCTAssertEqual(organizationalUnit, certificate.subject.organizationalUnitName) - XCTAssertEqual(organization, certificate.subject.organizationName) - case .unrecognized(let name, let organizationalUnit, let organization): - XCTAssertEqual(name, certificate.subject.commonName) - XCTAssertEqual(organizationalUnit, certificate.subject.organizationalUnitName) - XCTAssertEqual(organization, certificate.subject.organizationName) + let certificate = try Certificate(secIdentity: matches[0] as! SecIdentity) + let signingEntity = SigningEntity.from(certificate: certificate) + switch signingEntity { + case .recognized(_, let name, let organizationalUnit, let organization): + XCTAssertEqual(name, certificate.subject.commonName) + XCTAssertEqual(organizationalUnit, certificate.subject.organizationalUnitName) + XCTAssertEqual(organization, certificate.subject.organizationName) + case .unrecognized(let name, let organizationalUnit, let organization): + XCTAssertEqual(name, certificate.subject.commonName) + XCTAssertEqual(organizationalUnit, certificate.subject.organizationalUnitName) + XCTAssertEqual(organization, certificate.subject.organizationName) + } } - } #endif } diff --git a/Tests/PackageSigningTests/SigningIdentityTests.swift b/Tests/PackageSigningTests/SigningIdentityTests.swift index b426cce6b5f..da507396da1 100644 --- a/Tests/PackageSigningTests/SigningIdentityTests.swift +++ b/Tests/PackageSigningTests/SigningIdentityTests.swift @@ -14,7 +14,7 @@ import Foundation import Testing import XCTest -import _CryptoExtras // For RSA +import _CryptoExtras // For RSA import Basics import Crypto @testable import PackageSigning @@ -85,23 +85,23 @@ struct SigningIdentityTests { final class SigningIdentityXCTests: XCTestCase { #if os(macOS) - func testSigningIdentityFromKeychain() async throws { - #if ENABLE_REAL_SIGNING_IDENTITY_TEST - #else - try XCTSkipIf(true) - #endif + func testSigningIdentityFromKeychain() async throws { + #if ENABLE_REAL_SIGNING_IDENTITY_TEST + #else + try XCTSkipIf(true) + #endif - guard let label = Environment.current["REAL_SIGNING_IDENTITY_LABEL"] else { - throw XCTSkip("Skipping because 'REAL_SIGNING_IDENTITY_LABEL' env var is not set") - } - let identityStore = SigningIdentityStore(observabilityScope: ObservabilitySystem.NOOP) - let matches = identityStore.find(by: label) - XCTAssertTrue(!matches.isEmpty) + guard let label = Environment.current["REAL_SIGNING_IDENTITY_LABEL"] else { + throw XCTSkip("Skipping because 'REAL_SIGNING_IDENTITY_LABEL' env var is not set") + } + let identityStore = SigningIdentityStore(observabilityScope: ObservabilitySystem.NOOP) + let matches = identityStore.find(by: label) + XCTAssertTrue(!matches.isEmpty) - let subject = try Certificate(secIdentity: matches[0] as! SecIdentity).subject - XCTAssertNotNil(subject.commonName) - XCTAssertNotNil(subject.organizationalUnitName) - XCTAssertNotNil(subject.organizationName) - } + let subject = try Certificate(secIdentity: matches[0] as! SecIdentity).subject + XCTAssertNotNil(subject.commonName) + XCTAssertNotNil(subject.organizationalUnitName) + XCTAssertNotNil(subject.organizationName) + } #endif } diff --git a/Tests/PackageSigningTests/SigningTests.swift b/Tests/PackageSigningTests/SigningTests.swift index ed2e425b5e4..f95a0cee41a 100644 --- a/Tests/PackageSigningTests/SigningTests.swift +++ b/Tests/PackageSigningTests/SigningTests.swift @@ -10,14 +10,14 @@ // //===----------------------------------------------------------------------===// -import _CryptoExtras // for RSA +import _CryptoExtras // for RSA import Basics import Crypto import Foundation @testable import PackageSigning import _InternalTestSupport import SwiftASN1 -@testable import X509 // need internal APIs for OCSP testing +@testable import X509 // need internal APIs for OCSP testing import Testing struct SigningTests { @@ -26,7 +26,8 @@ struct SigningTests { let keyAndCertChain = try self.ecTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -73,7 +74,8 @@ struct SigningTests { let keyAndCertChain = try self.ecTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -118,7 +120,8 @@ struct SigningTests { let keyAndCertChain = try self.rsaTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(_RSA.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -163,7 +166,8 @@ struct SigningTests { let keyAndCertChain = try self.ecTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -182,7 +186,8 @@ struct SigningTests { } catch { guard case SigningError.keyDoesNotSupportSignatureAlgorithm = error else { Issue.record( - "Expected SigningError.keyDoesNotSupportSignatureAlgorithm but got \(error)") + "Expected SigningError.keyDoesNotSupportSignatureAlgorithm but got \(error)" + ) return } } @@ -193,7 +198,8 @@ struct SigningTests { let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -240,7 +246,8 @@ struct SigningTests { let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -285,7 +292,8 @@ struct SigningTests { let keyAndCertChain = try self.rsaSelfSignedTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(_RSA.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -349,7 +357,8 @@ struct SigningTests { let keyAndCertChain = try self.ecTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let signatureContent = Array("per aspera ad astra".utf8) @@ -388,7 +397,8 @@ struct SigningTests { let keyAndCertChain = try self.ecTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -402,7 +412,7 @@ struct SigningTests { ) let verifierConfiguration = VerifierConfiguration( - trustedRoots: [], // trust store is empty + trustedRoots: [], // trust store is empty includeDefaultTrustStore: false, certificateExpiration: .disabled, certificateRevocation: .disabled @@ -417,7 +427,8 @@ struct SigningTests { guard case .certificateNotTrusted = status else { Issue.record( - "Expected signature status to be .certificateNotTrusted but got \(status)") + "Expected signature status to be .certificateNotTrusted but got \(status)" + ) return } } @@ -427,7 +438,8 @@ struct SigningTests { let keyAndCertChain = try self.ecTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -459,7 +471,8 @@ struct SigningTests { guard case .certificateInvalid(let reason) = status else { Issue.record( - "Expected signature status to be .certificateInvalid but got \(status)") + "Expected signature status to be .certificateInvalid but got \(status)" + ) return } #expect(reason.contains("not yet valid")) @@ -484,7 +497,8 @@ struct SigningTests { guard case .certificateInvalid(let reason) = status else { Issue.record( - "Expected signature status to be .certificateInvalid but got \(status)") + "Expected signature status to be .certificateInvalid but got \(status)" + ) return } #expect(reason.contains("has expired")) @@ -559,9 +573,12 @@ struct SigningTests { ], privateKey: intermediatePrivateKey, responseExtensions: { nonce } - )) + ) + ) return HTTPClientResponse( - statusCode: 200, body: try Data(ocspResponse.derEncodedBytes())) + statusCode: 200, + body: try Data(ocspResponse.derEncodedBytes()) + ) default: throw StringError("method and url should match") } @@ -596,7 +613,8 @@ struct SigningTests { ) guard case .certificateInvalid(let reason) = status else { Issue.record( - "Expected signature status to be .certificateInvalid but got \(status)") + "Expected signature status to be .certificateInvalid but got \(status)" + ) return } #expect(reason.contains("status unknown")) @@ -631,7 +649,8 @@ struct SigningTests { let keyAndCertChain = try rsaADPKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(_RSA.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -667,11 +686,13 @@ struct SigningTests { try fixture(name: "Signing", createGitRepo: false) { fixturePath in let privateKey = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "development_key.p8" + pathComponents: "Certificates", + "development_key.p8" ) let certificate = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "development.cer" + pathComponents: "Certificates", + "development.cer" ) return KeyAndCertChain( @@ -689,7 +710,8 @@ struct SigningTests { let keyAndCertChain = try ecADPKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -725,11 +747,13 @@ struct SigningTests { try fixture(name: "Signing", createGitRepo: false) { fixturePath in let privateKey = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "swift_package_key.p8" + pathComponents: "Certificates", + "swift_package_key.p8" ) let certificate = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "swift_package.cer" + pathComponents: "Certificates", + "swift_package.cer" ) return KeyAndCertChain( @@ -761,14 +785,14 @@ struct SigningTests { let signature = try SignatureProvider.sign( content: content, identity: signingIdentity, - intermediateCertificates: [], // No need to pass intermediates for WWDR certs + intermediateCertificates: [], // No need to pass intermediates for WWDR certs format: signatureFormat, observabilityScope: ObservabilitySystem.NOOP ) let verifierConfiguration = VerifierConfiguration( trustedRoots: [], - includeDefaultTrustStore: true, // WWDR roots are in the default trust store + includeDefaultTrustStore: true, // WWDR roots are in the default trust store certificateExpiration: .enabled(validationTime: nil), certificateRevocation: .strict(validationTime: nil) ) @@ -816,13 +840,13 @@ struct SigningTests { let signature = try cmsProvider.sign( content: content, identity: signingIdentity, - intermediateCertificates: [], // No need to pass intermediates for WWDR certs + intermediateCertificates: [], // No need to pass intermediates for WWDR certs observabilityScope: ObservabilitySystem.NOOP ) let verifierConfiguration = VerifierConfiguration( trustedRoots: [], - includeDefaultTrustStore: true, // WWDR roots are in the default trust store + includeDefaultTrustStore: true, // WWDR roots are in the default trust store certificateExpiration: .enabled(validationTime: nil), certificateRevocation: .strict(validationTime: nil) ) @@ -869,13 +893,13 @@ struct SigningTests { let signature = try cmsProvider.sign( content: content, identity: signingIdentity, - intermediateCertificates: [], // No need to pass intermediates for WWDR certs + intermediateCertificates: [], // No need to pass intermediates for WWDR certs observabilityScope: ObservabilitySystem.NOOP ) let verifierConfiguration = VerifierConfiguration( trustedRoots: [], - includeDefaultTrustStore: true, // WWDR roots are in the default trust store + includeDefaultTrustStore: true, // WWDR roots are in the default trust store certificateExpiration: .enabled(validationTime: nil), certificateRevocation: .strict(validationTime: nil) ) @@ -907,7 +931,8 @@ struct SigningTests { let keyAndCertChain = try self.ecTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -948,7 +973,8 @@ struct SigningTests { let keyAndCertChain = try self.ecSelfSignedTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -989,7 +1015,8 @@ struct SigningTests { let keyAndCertChain = try self.ecTestKeyAndCertChain() let signingIdentity = SwiftSigningIdentity( certificate: try Certificate(keyAndCertChain.leafCertificate), - privateKey: try Certificate + privateKey: + try Certificate .PrivateKey(P256.Signing.PrivateKey(derRepresentation: keyAndCertChain.privateKey)) ) let content = Array("per aspera ad astra".utf8) @@ -1004,7 +1031,7 @@ struct SigningTests { ) let verifierConfiguration = VerifierConfiguration( - trustedRoots: [], // trust store is empty + trustedRoots: [], // trust store is empty includeDefaultTrustStore: false, certificateExpiration: .disabled, certificateRevocation: .disabled @@ -1020,7 +1047,8 @@ struct SigningTests { } catch { guard case SigningError.certificateNotTrusted = error else { Issue.record( - "Expected error to be SigningError.certificateNotTrusted but got \(error)") + "Expected error to be SigningError.certificateNotTrusted but got \(error)" + ) return } } @@ -1030,19 +1058,23 @@ struct SigningTests { try fixture(name: "Signing", createGitRepo: false) { fixturePath in let privateKey = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "Test_ec_key.p8" + pathComponents: "Certificates", + "Test_ec_key.p8" ) let certificate = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "Test_ec.cer" + pathComponents: "Certificates", + "Test_ec.cer" ) let intermediateCA = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "TestIntermediateCA.cer" + pathComponents: "Certificates", + "TestIntermediateCA.cer" ) let rootCA = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "TestRootCA.cer" + pathComponents: "Certificates", + "TestRootCA.cer" ) return KeyAndCertChain( @@ -1056,11 +1088,13 @@ struct SigningTests { try fixture(name: "Signing", createGitRepo: false) { fixturePath in let privateKey = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "Test_ec_self_signed_key.p8" + pathComponents: "Certificates", + "Test_ec_self_signed_key.p8" ) let certificate = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "Test_ec_self_signed.cer" + pathComponents: "Certificates", + "Test_ec_self_signed.cer" ) return KeyAndCertChain( @@ -1074,19 +1108,23 @@ struct SigningTests { try fixture(name: "Signing", createGitRepo: false) { fixturePath in let privateKey = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "Test_rsa_key.p8" + pathComponents: "Certificates", + "Test_rsa_key.p8" ) let certificate = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "Test_rsa.cer" + pathComponents: "Certificates", + "Test_rsa.cer" ) let intermediateCA = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "TestIntermediateCA.cer" + pathComponents: "Certificates", + "TestIntermediateCA.cer" ) let rootCA = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "TestRootCA.cer" + pathComponents: "Certificates", + "TestRootCA.cer" ) return KeyAndCertChain( @@ -1100,11 +1138,13 @@ struct SigningTests { try fixture(name: "Signing", createGitRepo: false) { fixturePath in let privateKey = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "Test_rsa_self_signed_key.p8" + pathComponents: "Certificates", + "Test_rsa_self_signed_key.p8" ) let certificate = try readFileContents( in: fixturePath, - pathComponents: "Certificates", "Test_rsa_self_signed.cer" + pathComponents: "Certificates", + "Test_rsa_self_signed.cer" ) return KeyAndCertChain( @@ -1172,7 +1212,7 @@ enum OCSPTestHelper { AuthorityInformationAccess.AccessDescription( method: .ocspServer, location: GeneralName.uniformResourceIdentifier(ocspServer) - ), + ) ]) } }, diff --git a/Tests/SPMBuildCoreTests/ArtifactsArchiveMetadataTests.swift b/Tests/SPMBuildCoreTests/ArtifactsArchiveMetadataTests.swift index 7b930563a25..a8f892072fd 100644 --- a/Tests/SPMBuildCoreTests/ArtifactsArchiveMetadataTests.swift +++ b/Tests/SPMBuildCoreTests/ArtifactsArchiveMetadataTests.swift @@ -21,26 +21,26 @@ struct ArtifactsArchiveMetadataTests { try fileSystem.writeFileContents( "/info.json", string: """ - { - "schemaVersion": "1.0", - "artifacts": { - "protocol-buffer-compiler": { - "type": "executable", - "version": "3.5.1", - "variants": [ - { - "path": "x86_64-apple-macosx/protoc", - "supportedTriples": ["x86_64-apple-macosx"] - }, - { - "path": "x86_64-unknown-linux-gnu/protoc", - "supportedTriples": ["x86_64-unknown-linux-gnu"] - } - ] + { + "schemaVersion": "1.0", + "artifacts": { + "protocol-buffer-compiler": { + "type": "executable", + "version": "3.5.1", + "variants": [ + { + "path": "x86_64-apple-macosx/protoc", + "supportedTriples": ["x86_64-apple-macosx"] + }, + { + "path": "x86_64-unknown-linux-gnu/protoc", + "supportedTriples": ["x86_64-unknown-linux-gnu"] + } + ] + } } } - } - """ + """ ) let metadata = try ArtifactsArchiveMetadata.parse(fileSystem: fileSystem, rootPath: .root) @@ -60,7 +60,7 @@ struct ArtifactsArchiveMetadataTests { supportedTriples: [Triple("x86_64-unknown-linux-gnu")] ), ] - ), + ) ] ) #expect(metadata == expected, "Actual is not as expected") @@ -72,25 +72,25 @@ struct ArtifactsArchiveMetadataTests { try fileSystem.writeFileContents( "/info.json", string: """ - { - "schemaVersion": "1.0", - "artifacts": { - "protocol-buffer-compiler": { - "type": "executable", - "version": "3.5.1", - "variants": [ - { - "path": "x86_64-apple-macosx/protoc" - }, - { - "path": "x86_64-unknown-linux-gnu/protoc", - "supportedTriples": null - } - ] + { + "schemaVersion": "1.0", + "artifacts": { + "protocol-buffer-compiler": { + "type": "executable", + "version": "3.5.1", + "variants": [ + { + "path": "x86_64-apple-macosx/protoc" + }, + { + "path": "x86_64-unknown-linux-gnu/protoc", + "supportedTriples": null + } + ] + } } } - } - """ + """ ) let metadata = try ArtifactsArchiveMetadata.parse(fileSystem: fileSystem, rootPath: .root) @@ -110,18 +110,22 @@ struct ArtifactsArchiveMetadataTests { supportedTriples: nil ), ] - ), + ) ] ) #expect(metadata == expected, "Actual is not as expected") let binaryTarget = BinaryModule( - name: "protoc", kind: .artifactsArchive(types: [.executable]), path: .root, origin: .local + name: "protoc", + kind: .artifactsArchive(types: [.executable]), + path: .root, + origin: .local ) // No supportedTriples with binaryTarget should be rejected #expect(throws: (any Error).self) { try binaryTarget.parseExecutableArtifactArchives( - for: Triple("x86_64-apple-macosx"), fileSystem: fileSystem + for: Triple("x86_64-apple-macosx"), + fileSystem: fileSystem ) } } diff --git a/Tests/SPMBuildCoreTests/MainAttrDetectionTests.swift b/Tests/SPMBuildCoreTests/MainAttrDetectionTests.swift index c7e3cdba562..1a6a7b6751a 100644 --- a/Tests/SPMBuildCoreTests/MainAttrDetectionTests.swift +++ b/Tests/SPMBuildCoreTests/MainAttrDetectionTests.swift @@ -22,234 +22,234 @@ struct MainAttrDetectionTests { arguments: [ ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - """, + """, expected: false, knownIssue: false, id: "Empty file", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - @main - struct MyApp { - static func main() { - print("Hello, World!") + @main + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: true, knownIssue: false, id: "Simple @main case", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - @main - struct MyApp { - static func main() { - print("Hello, World!") + @main + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: true, knownIssue: false, id: "@main with leading whitespace", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - // @main - struct MyApp { - static func main() { - print("Hello, World!") + // @main + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: false, knownIssue: false, id: "@main in single-line comment (should be ignored)", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - struct MyApp { - // This is @main but not at start - static func main() { - print("Hello, World!") + struct MyApp { + // This is @main but not at start + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: false, knownIssue: false, id: "@main not at beginning of line (should not match)", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - import Foundation - import SwiftUI + import Foundation + import SwiftUI - @main - struct MyApp: App { - var body: some Scene { - WindowGroup { - ContentView() + @main + struct MyApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } } } - } - """, + """, expected: true, knownIssue: false, id: "@main with imports and other code", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - @main - struct FirstApp { - static func main() { - print("First") + @main + struct FirstApp { + static func main() { + print("First") + } } - } - // @main (commented out) - struct SecondApp { - static func main() { - print("Second") + // @main (commented out) + struct SecondApp { + static func main() { + print("Second") + } } - } - """, + """, expected: true, knownIssue: false, id: "Multiple @main occurrences (first one should be detected)", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - @main - struct MyApp { - static func main() { - let text = "@main is cool" - print(text) + @main + struct MyApp { + static func main() { + let text = "@main is cool" + print(text) + } } - } - """, + """, expected: true, knownIssue: false, id: "@main in string literal (should still match as it's at line start)", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - struct MyApp { - static func main() { - print("Hello, World!") + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: false, knownIssue: false, id: "No @main, just regular code", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - \t @main - struct MyApp { - static func main() { - print("Hello, World!") + \t @main + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: true, knownIssue: false, id: "@main with tabs and spaces", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - /* - @main - */ - struct MyApp { - static func main() { - print("Hello, World!") + /* + @main + */ + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: false, knownIssue: false, id: "@main in multi-line comment (should be ignored)", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - /* @main */ - struct MyApp { - static func main() { - print("Hello, World!") + /* @main */ + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: false, knownIssue: false, id: "@main in multi-line comment on same line (should be ignored)", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - /* - Some comment - */ - @main - struct MyApp { - static func main() { - print("Hello, World!") + /* + Some comment + */ + @main + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: true, knownIssue: false, id: "@main after multi-line comment ends", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - // This is a comment - /* Multi-line - comment */ - @main - struct MyApp { - static func main() { - print("Hello, World!") + // This is a comment + /* Multi-line + comment */ + @main + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: true, knownIssue: false, id: "@main with mixed comments", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - /* - This is a multi-line comment - that spans multiple lines - @main should be ignored here - */ + /* + This is a multi-line comment + that spans multiple lines + @main should be ignored here + */ - @main - struct MyApp { - static func main() { - print("Hello, World!") + @main + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: true, knownIssue: false, id: "Complex multi-line comment scenario", ), ContainsAtMainReturnsExpectedValueTestData( fileContent: """ - /* - This is a multi-line comment - /* @main - struct MyApp { - static func main() { - print("Hello, World!") + /* + This is a multi-line comment + /* @main + struct MyApp { + static func main() { + print("Hello, World!") + } } - } - """, + """, expected: true, knownIssue: true, id: "Multi-line comment end on a line containing @main", - ) + ), ], ) func containsAtMainReturnsExpectedValue( diff --git a/Tests/SPMBuildCoreTests/XCFrameworkMetadataTests.swift b/Tests/SPMBuildCoreTests/XCFrameworkMetadataTests.swift index 2f2aa8b5bb8..ac6895505ba 100644 --- a/Tests/SPMBuildCoreTests/XCFrameworkMetadataTests.swift +++ b/Tests/SPMBuildCoreTests/XCFrameworkMetadataTests.swift @@ -18,7 +18,7 @@ struct XCFrameworkMetadataTests { @Test func parseFramework() throws { let fileSystem = InMemoryFileSystem(files: [ - "/Info.plist": """ + "/Info.plist": """ @@ -59,7 +59,7 @@ struct XCFrameworkMetadataTests { 1.0 - """, + """ ]) let metadata = try XCFrameworkMetadata.parse(fileSystem: fileSystem, rootPath: .root) @@ -117,7 +117,7 @@ struct XCFrameworkMetadataTests { 1.0 - """, + """ ]) let metadata = try XCFrameworkMetadata.parse(fileSystem: fileSystem, rootPath: .root) @@ -130,7 +130,7 @@ struct XCFrameworkMetadataTests { platform: "macos", architectures: ["x86_64"], variant: nil - ), + ) ], ) #expect(metadata == expected) diff --git a/Tests/SourceControlTests/GitRepositoryProviderTests.swift b/Tests/SourceControlTests/GitRepositoryProviderTests.swift index f9960dbc8f7..ad16df9a5a6 100644 --- a/Tests/SourceControlTests/GitRepositoryProviderTests.swift +++ b/Tests/SourceControlTests/GitRepositoryProviderTests.swift @@ -88,13 +88,16 @@ struct GitRepositoryProviderTests { let errorString = "\(error)" #expect( errorString.contains(stdOut), - "Error string '\(errorString)' should contain '\(stdOut)'") + "Error string '\(errorString)' should contain '\(stdOut)'" + ) #expect( errorString.contains(stdErr), - "Error string '\(errorString)' should contain '\(stdErr)'") + "Error string '\(errorString)' should contain '\(stdErr)'" + ) #expect( errorString.contains(command), - "Error string '\(errorString)' should contain '\(command)'") + "Error string '\(errorString)' should contain '\(command)'" + ) } @Test( @@ -114,7 +117,8 @@ struct GitRepositoryProviderTests { let errorString = "\(error)" #expect( errorString.contains(stdErr), - "Error string '\(errorString)' should contain '\(stdErr)'") + "Error string '\(errorString)' should contain '\(stdErr)'" + ) } @Test( diff --git a/Tests/SourceControlTests/GitRepositoryTests.swift b/Tests/SourceControlTests/GitRepositoryTests.swift index b9ee3871aaf..cea807032ab 100644 --- a/Tests/SourceControlTests/GitRepositoryTests.swift +++ b/Tests/SourceControlTests/GitRepositoryTests.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -@_spi(ProcessEnvironmentBlockShim) -import Basics +@_spi(ProcessEnvironmentBlockShim) import Basics @testable import SourceControl import _InternalTestSupport import XCTest @@ -136,17 +135,19 @@ class GitRepositoryTests: XCTestCase { try await testWithTemporaryDirectory { path in // Unarchive the static test repository. let inputArchivePath = AbsolutePath(#file).parentDirectory.appending(components: "Inputs", "TestRepo.tgz") -#if os(Windows) - try await AsyncProcess.checkNonZeroExit(args: "tar.exe", "-x", "-v", "-C", path.pathString, "-f", inputArchivePath.pathString) -#else - try await AsyncProcess.checkNonZeroExit(args: "tar", "--no-same-owner", "-x", "-v", "-C", path.pathString, "-f", inputArchivePath.pathString) -#endif + #if os(Windows) + try await AsyncProcess.checkNonZeroExit(args: "tar.exe", "-x", "-v", "-C", path.pathString, "-f", inputArchivePath.pathString) + #else + try await AsyncProcess.checkNonZeroExit(args: "tar", "--no-same-owner", "-x", "-v", "-C", path.pathString, "-f", inputArchivePath.pathString) + #endif let testRepoPath = path.appending("TestRepo") // Check hash resolution. let repo = GitRepository(path: testRepoPath) - XCTAssertEqual(try repo.resolveHash(treeish: "1.0", type: "commit"), - try repo.resolveHash(treeish: "master")) + XCTAssertEqual( + try repo.resolveHash(treeish: "1.0", type: "commit"), + try repo.resolveHash(treeish: "master") + ) // Get the initial commit. let initialCommitHash = try repo.resolveHash(treeish: "a8b9fcb") @@ -178,7 +179,7 @@ class GitRepositoryTests: XCTestCase { // paths with special characters. let funnyNamesCommit = try repo.readCommit(hash: repo.resolveHash(treeish: "a7b19a7")) let funnyNamesRoot = try repo.readTree(hash: funnyNamesCommit.tree) - XCTAssertEqual(funnyNamesRoot.contents.map{ $0.name }, ["README.txt", "funny-names", "subdir"]) + XCTAssertEqual(funnyNamesRoot.contents.map { $0.name }, ["README.txt", "funny-names", "subdir"]) guard funnyNamesRoot.contents.count == 3 else { return XCTFail() } // FIXME: This isn't yet supported. @@ -187,7 +188,7 @@ class GitRepositoryTests: XCTestCase { if let _ = try? repo.readTree(location: funnyNamesSubdirEntry.location) { XCTFail("unexpected success reading tree with funny names") } - } + } } func testSubmoduleRead() throws { @@ -202,7 +203,12 @@ class GitRepositoryTests: XCTestCase { initGitRepo(repoPath) try AsyncProcess.checkNonZeroExit( - args: Git.tool, "-C", repoPath.pathString, "submodule", "add", testRepoPath.pathString, + args: Git.tool, + "-C", + repoPath.pathString, + "submodule", + "add", + testRepoPath.pathString, environment: .init(Git.environmentBlock) ) let repo = GitRepository(path: repoPath) @@ -258,9 +264,9 @@ class GitRepositoryTests: XCTestCase { XCTAssert(view.isFile("/test-file-1.txt")) XCTAssert(!view.isSymlink("/test-file-1.txt")) XCTAssert(!view.isExecutableFile("/does-not-exist")) -#if !os(Windows) - XCTAssert(view.isExecutableFile("/test-file-3.sh")) -#endif + #if !os(Windows) + XCTAssert(view.isExecutableFile("/test-file-3.sh")) + #endif // Check read of a directory. let subdirPath = AbsolutePath("/subdir") @@ -450,8 +456,7 @@ class GitRepositoryTests: XCTestCase { do { try repo.setURL(remote: "fake", url: "../bar") XCTFail("unexpected success (shouldn’t have been able to set URL of missing remote)") - } - catch let error as GitRepositoryError { + } catch let error as GitRepositoryError { XCTAssertEqual(error.path, testRepoPath) XCTAssertNotNil(error.diagnosticLocation) } @@ -628,7 +633,13 @@ class GitRepositoryTests: XCTestCase { // Add submodule to foo and tag it as 1.0.1 try foo.checkout(newBranch: "submodule") try await AsyncProcess.checkNonZeroExit( - args: Git.tool, "-C", fooPath.pathString, "submodule", "add", barPath.pathString, "bar", + args: Git.tool, + "-C", + fooPath.pathString, + "submodule", + "add", + barPath.pathString, + "bar", environment: .init(Git.environmentBlock) ) @@ -650,7 +661,13 @@ class GitRepositoryTests: XCTestCase { try localFileSystem.writeFileContents(barPath.appending("bar.txt"), bytes: "hello") // Add a submodule too to check for recursive submodules. try await AsyncProcess.checkNonZeroExit( - args: Git.tool, "-C", barPath.pathString, "submodule", "add", bazPath.pathString, "baz", + args: Git.tool, + "-C", + barPath.pathString, + "submodule", + "add", + bazPath.pathString, + "baz", environment: .init(Git.environmentBlock) ) @@ -821,7 +838,7 @@ class GitRepositoryTests: XCTestCase { // We consider the directory valid even if the remote does not have the same path extension - in this case we expected '.git'. XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(url: SourceControlURL(customRemoteWithoutPathExtension)))) // We consider the directory valid even if the remote does not have the same path extension - in this case we expected '.git'. - XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(url: SourceControlURL((customRemote as NSString).deletingPathExtension + "/")))) + XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(url: SourceControlURL((customRemote as NSString).deletingPathExtension + "/")))) // The following ensure that are actually checking the remote's origin. XCTAssertFalse(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(path: AbsolutePath(validating: "/")))) @@ -871,8 +888,8 @@ class GitRepositoryTests: XCTestCase { XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(path: try AbsolutePath(validating: customRemotePathWithoutPathExtension)))) XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(url: SourceControlURL(customRemotePathWithoutPathExtension)))) // We consider the directory valid even if the remote does not have the same path extension - in this case we expected '.git'. - XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(path: try AbsolutePath(validating: customRemotePathWithoutPathExtension + "/")))) - XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(url: SourceControlURL((customRemotePath as NSString).deletingPathExtension + "/")))) + XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(path: try AbsolutePath(validating: customRemotePathWithoutPathExtension + "/")))) + XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(url: SourceControlURL((customRemotePath as NSString).deletingPathExtension + "/")))) // The following ensure that are actually checking the remote's origin. XCTAssertFalse(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(path: AbsolutePath(validating: "/")))) @@ -917,7 +934,7 @@ class GitRepositoryTests: XCTestCase { // We consider the directory valid even if the remote does not have the same path extension - in this case we expected '.git'. XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(url: SourceControlURL("https://mycustomdomain/some-package")))) // We consider the directory valid even if the remote does not have the same path extension - in this case we expected '.git'. - XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(url: SourceControlURL("https://mycustomdomain/some-package/")))) + XCTAssertTrue(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(url: SourceControlURL("https://mycustomdomain/some-package/")))) // The following ensure that are actually checking the remote's origin. XCTAssertFalse(try repositoryManager.isValidDirectory(packageDir, for: RepositorySpecifier(path: AbsolutePath(validating: "/")))) diff --git a/Tests/SourceControlTests/RepositoryManagerTests.swift b/Tests/SourceControlTests/RepositoryManagerTests.swift index 10b354b451f..6c7f62534e8 100644 --- a/Tests/SourceControlTests/RepositoryManagerTests.swift +++ b/Tests/SourceControlTests/RepositoryManagerTests.swift @@ -150,10 +150,14 @@ final class RepositoryManagerTests: XCTestCase { try XCTAssertDirectoryExists(cachePath.appending(repo.storagePath())) try XCTAssertDirectoryExists(repositoriesPath.appending(repo.storagePath())) try delegate.wait(timeout: .now() + 2) - XCTAssertEqual(delegate.willFetch[0].details, - RepositoryManager.FetchDetails(fromCache: false, updatedCache: false)) - XCTAssertEqual(try delegate.didFetch[0].result.get(), - RepositoryManager.FetchDetails(fromCache: false, updatedCache: true)) + XCTAssertEqual( + delegate.willFetch[0].details, + RepositoryManager.FetchDetails(fromCache: false, updatedCache: false) + ) + XCTAssertEqual( + try delegate.didFetch[0].result.get(), + RepositoryManager.FetchDetails(fromCache: false, updatedCache: true) + ) // removing the repositories path to force re-fetch try fs.removeFileTree(repositoriesPath) @@ -164,10 +168,14 @@ final class RepositoryManagerTests: XCTestCase { XCTAssertNoDiagnostics(observability.diagnostics) try XCTAssertDirectoryExists(repositoriesPath.appending(repo.storagePath())) try delegate.wait(timeout: .now() + 2) - XCTAssertEqual(delegate.willFetch[1].details, - RepositoryManager.FetchDetails(fromCache: true, updatedCache: false)) - XCTAssertEqual(try delegate.didFetch[1].result.get(), - RepositoryManager.FetchDetails(fromCache: true, updatedCache: true)) + XCTAssertEqual( + delegate.willFetch[1].details, + RepositoryManager.FetchDetails(fromCache: true, updatedCache: false) + ) + XCTAssertEqual( + try delegate.didFetch[1].result.get(), + RepositoryManager.FetchDetails(fromCache: true, updatedCache: true) + ) // reset the state on disk try fs.removeFileTree(cachePath) @@ -180,10 +188,14 @@ final class RepositoryManagerTests: XCTestCase { try XCTAssertDirectoryExists(cachePath.appending(repo.storagePath())) try XCTAssertDirectoryExists(repositoriesPath.appending(repo.storagePath())) try delegate.wait(timeout: .now() + 2) - XCTAssertEqual(delegate.willFetch[2].details, - RepositoryManager.FetchDetails(fromCache: false, updatedCache: false)) - XCTAssertEqual(try delegate.didFetch[2].result.get(), - RepositoryManager.FetchDetails(fromCache: false, updatedCache: true)) + XCTAssertEqual( + delegate.willFetch[2].details, + RepositoryManager.FetchDetails(fromCache: false, updatedCache: false) + ) + XCTAssertEqual( + try delegate.didFetch[2].result.get(), + RepositoryManager.FetchDetails(fromCache: false, updatedCache: true) + ) // update packages from the cache delegate.prepare(fetchExpected: false, updateExpected: true) @@ -351,7 +363,7 @@ final class RepositoryManagerTests: XCTestCase { let results = ThreadSafeKeyValueStore() let concurrency = 10000 try await withThrowingTaskGroup(of: Void.self) { group in - for index in 0 ..< concurrency { + for index in 0.. 0) results[index] = try await manager.lookup( @@ -374,7 +386,7 @@ final class RepositoryManagerTests: XCTestCase { XCTAssertEqual(delegate.didUpdate.count, concurrency - 1) XCTAssertEqual(results.count, concurrency) - for index in 0 ..< concurrency { + for index in 0..>() - for index in 0 ..< total { + for index in 0.. WorkingCheckout { + func createWorkingCopy(repository: RepositorySpecifier, sourcePath: AbsolutePath, at destinationPath: AbsolutePath, editable: Bool) async throws -> WorkingCheckout { try self.fileSystem.createDirectory(destinationPath) try self.fileSystem.writeFileContents(destinationPath.appending("README.txt"), bytes: "Hi") return try await self.openWorkingCopy(at: destinationPath) @@ -795,7 +807,7 @@ private class DummyRepositoryProvider: RepositoryProvider, @unchecked Sendable { } struct DummyWorkingCheckout: WorkingCheckout { - let path : AbsolutePath + let path: AbsolutePath init(at path: AbsolutePath) { self.path = path @@ -857,12 +869,12 @@ fileprivate class DummyRepositoryManagerDelegate: RepositoryManager.Delegate, @u public func prepare(fetchExpected: Bool, updateExpected: Bool) { if fetchExpected { - self.group.enter() // will fetch - self.group.enter() // did fetch + self.group.enter() // will fetch + self.group.enter() // did fetch } if updateExpected { - self.group.enter() // will update - self.group.enter() // did v + self.group.enter() // will update + self.group.enter() // did v } } diff --git a/Tests/SourceKitLSPAPITests/SourceKitLSPAPITests.swift b/Tests/SourceKitLSPAPITests/SourceKitLSPAPITests.swift index cb99502be38..22e9cba0c0b 100644 --- a/Tests/SourceKitLSPAPITests/SourceKitLSPAPITests.swift +++ b/Tests/SourceKitLSPAPITests/SourceKitLSPAPITests.swift @@ -13,8 +13,7 @@ import Basics import Build -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph import PackageModel @testable import SourceKitLSPAPI @@ -24,8 +23,9 @@ import XCTest final class SourceKitLSPAPITests: XCTestCase { func testBasicSwiftPackage() async throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Pkg/Sources/exe/main.swift", + let fs = InMemoryFileSystem( + emptyFiles: + "/Pkg/Sources/exe/main.swift", "/Pkg/Sources/exe/README.md", "/Pkg/Sources/exe/exe.docc/GettingStarted.md", "/Pkg/Sources/exe/Resources/some_file.txt", @@ -56,8 +56,9 @@ final class SourceKitLSPAPITests: XCTestCase { dependencies: [], resources: [.init(rule: .copy, path: "Resources/some_file.txt")] ), - TargetDescription(name: "plugin", type: .plugin, pluginCapability: .buildTool) - ]), + TargetDescription(name: "plugin", type: .plugin, pluginCapability: .buildTool), + ] + ) ], observabilityScope: observability.topScope ) @@ -86,7 +87,7 @@ final class SourceKitLSPAPITests: XCTestCase { "-package-name", "pkg", "-emit-dependencies", "-emit-module", - "-emit-module-path", AbsolutePath("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/Modules/exe.swiftmodule").pathString + "-emit-module-path", AbsolutePath("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/Modules/exe.swiftmodule").pathString, ], resources: [.init(filePath: "/Pkg/Sources/exe/Resources/some_file.txt")], ignoredFiles: [.init(filePath: "/Pkg/Sources/exe/exe.docc")], @@ -101,7 +102,7 @@ final class SourceKitLSPAPITests: XCTestCase { "-package-name", "pkg", "-emit-dependencies", "-emit-module", - "-emit-module-path", AbsolutePath("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/Modules/lib.swiftmodule").pathString + "-emit-module-path", AbsolutePath("/path/to/build/\(plan.destinationBuildParameters.triple)/debug/Modules/lib.swiftmodule").pathString, ], resources: [.init(filePath: "/Pkg/Sources/lib/Resources/some_file.txt")], ignoredFiles: [.init(filePath: "/Pkg/Sources/lib/lib.docc")], @@ -112,7 +113,7 @@ final class SourceKitLSPAPITests: XCTestCase { for: "plugin", graph: graph, partialArguments: [ - "-I", AbsolutePath("/fake/manifestLib/path").pathString + "-I", AbsolutePath("/fake/manifestLib/path").pathString, ], isPartOfRootPackage: true, destination: .host @@ -122,7 +123,7 @@ final class SourceKitLSPAPITests: XCTestCase { func testModuleTraversal() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/Pkg/Sources/exe/main.swift", + "/Pkg/Sources/exe/main.swift", "/Pkg/Sources/lib/lib.swift", "/Pkg/Plugins/plugin/plugin.swift" ) @@ -144,7 +145,7 @@ final class SourceKitLSPAPITests: XCTestCase { pluginCapability: .buildTool ), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -200,7 +201,7 @@ final class SourceKitLSPAPITests: XCTestCase { func testModuleTraversalRecordsDependencyOfVisitedNode() async throws { let fs = InMemoryFileSystem( emptyFiles: - "/Pkg/Sources/exe/main.swift", + "/Pkg/Sources/exe/main.swift", "/Pkg/Sources/lib/lib.swift" ) @@ -213,9 +214,9 @@ final class SourceKitLSPAPITests: XCTestCase { path: "/Pkg", targets: [ TargetDescription(name: "exe", dependencies: ["lib"]), - TargetDescription(name: "lib", dependencies: []) + TargetDescription(name: "lib", dependencies: []), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -257,8 +258,9 @@ final class SourceKitLSPAPITests: XCTestCase { } func testLoadPackage() async throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Pkg/Sources/lib/lib.swift" + let fs = InMemoryFileSystem( + emptyFiles: + "/Pkg/Sources/lib/lib.swift" ) let observability = ObservabilitySystem.makeForTesting() @@ -274,7 +276,8 @@ final class SourceKitLSPAPITests: XCTestCase { name: "lib", dependencies: [] ) - ]), + ] + ) ], observabilityScope: observability.topScope ) @@ -313,7 +316,7 @@ final class SourceKitLSPAPITests: XCTestCase { "-package-name", "pkg", "-emit-dependencies", "-emit-module", - "-emit-module-path", AbsolutePath("/path/to/build/\(destinationBuildParameters.triple)/debug/Modules/lib.swiftmodule").pathString + "-emit-module-path", AbsolutePath("/path/to/build/\(destinationBuildParameters.triple)/debug/Modules/lib.swiftmodule").pathString, ], isPartOfRootPackage: true ) @@ -321,8 +324,9 @@ final class SourceKitLSPAPITests: XCTestCase { } func testClangOutputPaths() async throws { - let fs = InMemoryFileSystem(emptyFiles: - "/Pkg/Sources/lib/include/lib.h", + let fs = InMemoryFileSystem( + emptyFiles: + "/Pkg/Sources/lib/include/lib.h", "/Pkg/Sources/lib/lib.cpp" ) @@ -339,7 +343,8 @@ final class SourceKitLSPAPITests: XCTestCase { name: "lib", dependencies: [] ) - ]), + ] + ) ], observabilityScope: observability.topScope ) diff --git a/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift b/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift index 80f00260ee5..cfc46edf4a5 100644 --- a/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift +++ b/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift @@ -153,9 +153,11 @@ struct PIFBuilderTests { @Test func platformConditionBasics() async throws { try await withGeneratedPIF(fromFixture: "PIFBuilder/UnknownPlatforms") { pif, observabilitySystem in // We should emit a warning to the PIF log about the unknown platform - #expect(observabilitySystem.diagnostics.filter { - $0.severity == .warning && $0.message.contains("Ignoring settings assignments for unknown platform 'DoesNotExist'") - }.count > 0) + #expect( + observabilitySystem.diagnostics.filter { + $0.severity == .warning && $0.message.contains("Ignoring settings assignments for unknown platform 'DoesNotExist'") + }.count > 0 + ) let releaseConfig = try pif.workspace .project(named: "UnknownPlatforms") @@ -179,12 +181,12 @@ struct PIFBuilderTests { for platform in ProjectModel.BuildSettings.Platform.allCases { let ld_flags = releaseConfig.impartedBuildProperties.settings[.OTHER_LDFLAGS, platform] switch platform { - case .macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .xrOS, .driverKit, .freebsd: - #expect(ld_flags == ["-lc++", "$(inherited)"], "for platform \(platform)") - case .android, .linux, .wasi, .openbsd: - #expect(ld_flags == ["-lstdc++", "$(inherited)"], "for platform \(platform)") - case .windows, ._iOSDevice: - #expect(ld_flags == nil, "for platform \(platform)") + case .macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .xrOS, .driverKit, .freebsd: + #expect(ld_flags == ["-lc++", "$(inherited)"], "for platform \(platform)") + case .android, .linux, .wasi, .openbsd: + #expect(ld_flags == ["-lstdc++", "$(inherited)"], "for platform \(platform)") + case .windows, ._iOSDevice: + #expect(ld_flags == nil, "for platform \(platform)") } } } @@ -233,9 +235,11 @@ struct PIFBuilderTests { @Test func impartedModuleMaps() async throws { try await withGeneratedPIF(fromFixture: "CFamilyTargets/ModuleMapGenerationCases") { pif, observabilitySystem in - #expect(observabilitySystem.diagnostics.filter { - $0.severity == .error - }.isEmpty) + #expect( + observabilitySystem.diagnostics.filter { + $0.severity == .error + }.isEmpty + ) do { let releaseConfig = try pif.workspace @@ -268,9 +272,11 @@ struct PIFBuilderTests { @Test func disablingLocalRpaths() async throws { try await withGeneratedPIF(fromFixture: "Miscellaneous/Simple") { pif, observabilitySystem in - #expect(observabilitySystem.diagnostics.filter { - $0.severity == .error - }.isEmpty) + #expect( + observabilitySystem.diagnostics.filter { + $0.severity == .error + }.isEmpty + ) do { let releaseConfig = try pif.workspace @@ -283,9 +289,11 @@ struct PIFBuilderTests { } try await withGeneratedPIF(fromFixture: "Miscellaneous/Simple", addLocalRpaths: false) { pif, observabilitySystem in - #expect(observabilitySystem.diagnostics.filter { - $0.severity == .error - }.isEmpty) + #expect( + observabilitySystem.diagnostics.filter { + $0.severity == .error + }.isEmpty + ) do { let releaseConfig = try pif.workspace diff --git a/Tests/SwiftFixItTests/BasicTests.swift b/Tests/SwiftFixItTests/BasicTests.swift index 2198c6e174a..121a8a9cbd9 100644 --- a/Tests/SwiftFixItTests/BasicTests.swift +++ b/Tests/SwiftFixItTests/BasicTests.swift @@ -41,9 +41,9 @@ struct BasicTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] - ), + ) ] ) } @@ -69,11 +69,11 @@ struct BasicTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] - ), + ) ] - ), + ) ] ) } @@ -99,9 +99,9 @@ struct BasicTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] - ), + ) ] ), PrimaryDiagnostic( @@ -118,9 +118,9 @@ struct BasicTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22" - ), + ) ] - ), + ) ] ), ] @@ -134,17 +134,17 @@ struct BasicTests { .init( edits: .init( input: """ - var x = 1 - var y = 2 - var z = 3 - var w = foo(1, 2) - """, + var x = 1 + var y = 2 + var z = 3 + var w = foo(1, 2) + """, result: """ - let x = 1 - var y = 244 - z = 3 - w = fooo(1, 233) - """ + let x = 1 + var y = 244 + z = 3 + w = fooo(1, 233) + """ ), summary: .init(numberOfFixItsApplied: 2, numberOfFilesChanged: 1), diagnostics: [ @@ -230,7 +230,7 @@ struct BasicTests { text: "let" ), ] - ), + ) ] ) } @@ -257,7 +257,7 @@ struct BasicTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 6), text: "_" - ), + ) ] ), PrimaryDiagnostic( @@ -270,7 +270,7 @@ struct BasicTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), ] @@ -298,7 +298,7 @@ struct BasicTests { start: .init(path: path1, line: 1, column: 1), end: .init(path: path1, line: 1, column: 4), text: "let" - ), + ) ] ), PrimaryDiagnostic( @@ -310,7 +310,7 @@ struct BasicTests { start: .init(path: path1, line: 1, column: 5), end: .init(path: path1, line: 1, column: 6), text: "_" - ), + ) ] ), // path2 @@ -323,7 +323,7 @@ struct BasicTests { start: .init(path: path2, line: 1, column: 5), end: .init(path: path2, line: 1, column: 6), text: "_" - ), + ) ] ), PrimaryDiagnostic( @@ -335,7 +335,7 @@ struct BasicTests { start: .init(path: path2, line: 1, column: 1), end: .init(path: path2, line: 1, column: 4), text: "let" - ), + ) ] ), ] @@ -366,11 +366,11 @@ struct BasicTests { start: .init(path: path1, line: 1, column: 1), end: .init(path: path1, line: 1, column: 4), text: "let" - ), + ) ] - ), + ) ] - ), + ) ] ) } @@ -396,9 +396,9 @@ struct BasicTests { start: .init(path: path1, line: 1, column: 1), end: .init(path: path1, line: 1, column: 4), text: "let" - ), + ) ] - ), + ) ] ) } diff --git a/Tests/SwiftFixItTests/CategoryTests.swift b/Tests/SwiftFixItTests/CategoryTests.swift index 28b2af12119..bf0d1fced70 100644 --- a/Tests/SwiftFixItTests/CategoryTests.swift +++ b/Tests/SwiftFixItTests/CategoryTests.swift @@ -31,7 +31,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), PrimaryDiagnostic( @@ -45,7 +45,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 6), text: "_" - ), + ) ] ), ] @@ -76,9 +76,9 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] - ), + ) ] ), PrimaryDiagnostic( @@ -102,7 +102,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 6), text: "_" - ), + ) ] ), ] @@ -124,9 +124,9 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22", - ), + ) ] - ), + ) ] ), ] @@ -151,7 +151,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), PrimaryDiagnostic( @@ -165,7 +165,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22", - ), + ) ] ), ] @@ -200,7 +200,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let", - ), + ) ] ), ] @@ -216,7 +216,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22", - ), + ) ] ), PrimaryDiagnostic( @@ -236,9 +236,9 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 6), text: "_" - ), + ) ] - ), + ) ] ), ] @@ -264,7 +264,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), PrimaryDiagnostic( @@ -278,7 +278,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22", - ), + ) ] ), ] @@ -313,7 +313,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let", - ), + ) ] ), ] @@ -329,7 +329,7 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22", - ), + ) ] ), PrimaryDiagnostic( @@ -349,9 +349,9 @@ struct CategoryTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 6), text: "_" - ), + ) ] - ), + ) ] ), ] diff --git a/Tests/SwiftFixItTests/FilteringTests.swift b/Tests/SwiftFixItTests/FilteringTests.swift index 653bb7ecae9..b20cf5726d3 100644 --- a/Tests/SwiftFixItTests/FilteringTests.swift +++ b/Tests/SwiftFixItTests/FilteringTests.swift @@ -30,7 +30,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), PrimaryDiagnostic( @@ -43,7 +43,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22" - ), + ) ] ), PrimaryDiagnostic( @@ -64,7 +64,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 6), text: "_" - ), + ) ] ), ] @@ -91,7 +91,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), PrimaryDiagnostic( @@ -104,7 +104,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22" - ), + ) ] ), PrimaryDiagnostic( @@ -125,7 +125,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 6), text: "_" - ), + ) ] ), ] @@ -148,7 +148,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 7), end: .init(path: path, line: 1, column: 8), text: ":" - ), + ) ] ), ] @@ -179,7 +179,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), Note( @@ -191,7 +191,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22" - ), + ) ] ), ] @@ -210,7 +210,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 6), text: "y" - ), + ) ] ), // This separator note should not make a difference. @@ -227,7 +227,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 7), end: .init(path: path, line: 1, column: 8), text: ":" - ), + ) ] ), ] @@ -254,7 +254,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), PrimaryDiagnostic( @@ -271,7 +271,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 10), end: .init(path: path, line: 1, column: 11), text: "22" - ), + ) ] ), Note( @@ -294,9 +294,9 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 6), text: "y" - ), + ) ] - ), + ) ] ), PrimaryDiagnostic( @@ -309,7 +309,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 7), end: .init(path: path, line: 1, column: 8), text: ":" - ), + ) ] ), PrimaryDiagnostic( @@ -322,7 +322,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 14), end: .init(path: path, line: 1, column: 14), text: "3" - ), + ) ] ), ] @@ -352,7 +352,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), PrimaryDiagnostic( @@ -365,7 +365,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 4), text: "let" - ), + ) ] ), // On notes. @@ -383,9 +383,9 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22" - ), + ) ] - ), + ) ] ), PrimaryDiagnostic( @@ -402,9 +402,9 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 10), text: "22" - ), + ) ] - ), + ) ] ), ] @@ -437,7 +437,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 1), text: "@W " - ), + ) ] ), PrimaryDiagnostic( @@ -454,9 +454,9 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 9), text: "2" - ), + ) ] - ), + ) ] ), PrimaryDiagnostic( @@ -469,7 +469,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 1), end: .init(path: path, line: 1, column: 1), text: "@W " - ), + ) ] ), PrimaryDiagnostic( @@ -482,7 +482,7 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 5), text: "y" - ), + ) ] ), PrimaryDiagnostic( @@ -499,9 +499,9 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 9), end: .init(path: path, line: 1, column: 9), text: "2" - ), + ) ] - ), + ) ] ), PrimaryDiagnostic( @@ -518,9 +518,9 @@ struct FilteringTests { start: .init(path: path, line: 1, column: 5), end: .init(path: path, line: 1, column: 5), text: "y" - ), + ) ] - ), + ) ] ), ] @@ -555,7 +555,7 @@ struct FilteringTests { start: .init(path: path1, line: 1, column: 5), end: .init(path: path1, line: 1, column: 6), text: "y" - ), + ) ] ), PrimaryDiagnostic( @@ -572,9 +572,9 @@ struct FilteringTests { start: .init(path: path1, line: 1, column: 9), end: .init(path: path1, line: 1, column: 10), text: "2" - ), + ) ] - ), + ) ] ), // path2. @@ -588,7 +588,7 @@ struct FilteringTests { start: .init(path: path2, line: 1, column: 5), end: .init(path: path2, line: 1, column: 6), text: "y" - ), + ) ] ), PrimaryDiagnostic( @@ -605,9 +605,9 @@ struct FilteringTests { start: .init(path: path2, line: 1, column: 9), end: .init(path: path2, line: 1, column: 10), text: "2" - ), + ) ] - ), + ) ] ), ] diff --git a/Tests/SwiftFixItTests/Utilities.swift b/Tests/SwiftFixItTests/Utilities.swift index ee3959b8d1d..762938be0b8 100644 --- a/Tests/SwiftFixItTests/Utilities.swift +++ b/Tests/SwiftFixItTests/Utilities.swift @@ -14,8 +14,7 @@ import _InternalTestSupport import struct Basics.AbsolutePath import var Basics.localFileSystem import struct Foundation.UUID -@testable -import SwiftFixIt +@testable import SwiftFixIt import class SwiftSyntax.SourceLocationConverter import Testing import struct TSCUtility.SerializedDiagnostics @@ -126,13 +125,14 @@ struct PrimaryDiagnostic { fixIts: [FixIt] = [], notes: [Note] = [], ) { - let level: SerializedDiagnostics.Diagnostic.Level = switch level { - case .ignored: .ignored - case .warning: .warning - case .error: .error - case .fatal: .fatal - case .remark: .remark - } + let level: SerializedDiagnostics.Diagnostic.Level = + switch level { + case .ignored: .ignored + case .warning: .warning + case .error: .error + case .fatal: .fatal + case .remark: .remark + } self.diagnostic = .init( level: level, text: text, @@ -220,9 +220,11 @@ private func _testAPI( let flatDiagnostics: [Diagnostic] do { - let converters = Dictionary(uniqueKeysWithValues: sourceFilePathsAndEdits.map { path, edit in - (path, SourceLocationConverter(file: path.pathString, source: edit.input)) - }) + let converters = Dictionary( + uniqueKeysWithValues: sourceFilePathsAndEdits.map { path, edit in + (path, SourceLocationConverter(file: path.pathString, source: edit.input)) + } + ) flatDiagnostics = diagnostics.reduce(into: Array()) { partialResult, primaryDiagnostic in partialResult.append(primaryDiagnostic.diagnostic.withSourceLocationOffsets(using: converters)) @@ -248,7 +250,9 @@ private func _testAPI( if expectedContents != actualContents { Issue.record( title: "File #\(i + 1) (original/expected/actual contents)", - comparisonComponents: originalContents, expectedContents, actualContents, + comparisonComponents: originalContents, + expectedContents, + actualContents, sourceLocation: edit.locationInTest ) } @@ -257,7 +261,8 @@ private func _testAPI( if expectedSummary.summary != actualSummary { Issue.record( title: "Expected/actual change summaries", - comparisonComponents: expectedSummary.summary, actualSummary, + comparisonComponents: expectedSummary.summary, + actualSummary, sourceLocation: expectedSummary.locationInTest ) } diff --git a/Tests/WorkspaceTests/AuthorizationProviderTests.swift b/Tests/WorkspaceTests/AuthorizationProviderTests.swift index a49d0e44705..1917b358abb 100644 --- a/Tests/WorkspaceTests/AuthorizationProviderTests.swift +++ b/Tests/WorkspaceTests/AuthorizationProviderTests.swift @@ -151,7 +151,8 @@ fileprivate struct AuthorizationProviderTests { // Even if user .netrc file doesn't exist, the provider will be non-nil but contain no data. let expectedAuthorizationProvider = try resolveSymlinks(userPath) let authorizationProvider: NetrcAuthorizationProvider = try #require( - authorizationProviderOpt) + authorizationProviderOpt + ) #expect(authorizationProvider.path == expectedAuthorizationProvider) #expect(authorizationProvider.machines.isEmpty) } diff --git a/Tests/WorkspaceTests/InitTests.swift b/Tests/WorkspaceTests/InitTests.swift index ddc8efe0b92..6c167460810 100644 --- a/Tests/WorkspaceTests/InitTests.swift +++ b/Tests/WorkspaceTests/InitTests.swift @@ -19,14 +19,14 @@ import XCTest final class InitTests: XCTestCase { // MARK: TSCBasic package creation for each package type. - + func testInitPackageEmpty() throws { try testWithTemporaryDirectory { tmpPath in let fs = localFileSystem let path = tmpPath.appending("Foo") let name = path.basename try fs.createDirectory(path) - + // Create the package let initPackage = try InitPackage( name: name, @@ -54,7 +54,7 @@ final class InitTests: XCTestCase { } } - func testInitPackageExecutable() async throws { + func testInitPackageExecutable() async throws { try await testWithTemporaryDirectory { tmpPath in let fs = localFileSystem let path = tmpPath.appending("Foo") @@ -76,7 +76,7 @@ final class InitTests: XCTestCase { // Not picky about the specific progress messages, just checking that we got some. XCTAssertGreaterThan(progressMessages.count, 0) - + // Verify basic file system content that we expect in the package let manifest = path.appending("Package.swift") XCTAssertFileExists(manifest) @@ -92,11 +92,11 @@ final class InitTests: XCTestCase { ) let triple = try UserToolchain.default.targetTriple let binPath = path.appending(components: ".build", triple.platformBuildPathComponent, "debug") -#if os(Windows) - XCTAssertFileExists(binPath.appending("Foo.exe")) -#else - XCTAssertFileExists(binPath.appending("Foo")) -#endif + #if os(Windows) + XCTAssertFileExists(binPath.appending("Foo.exe")) + #else + XCTAssertFileExists(binPath.appending("Foo")) + #endif XCTAssertFileExists(binPath.appending(components: "Modules", "Foo.swiftmodule")) } } @@ -164,10 +164,13 @@ final class InitTests: XCTestCase { let testFile = tests.appending("FooTests").appending("FooTests.swift") let testFileContents: String = try localFileSystem.readFileContents(testFile) - XCTAssertTrue(testFileContents.hasPrefix("import XCTest"), """ - Validates formatting of XCTest source file, in particular that it does not contain leading whitespace: - \(testFileContents) - """) + XCTAssertTrue( + testFileContents.hasPrefix("import XCTest"), + """ + Validates formatting of XCTest source file, in particular that it does not contain leading whitespace: + \(testFileContents) + """ + ) XCTAssertMatch(testFileContents, .contains("func testExample() throws")) // Try building it @@ -208,15 +211,15 @@ final class InitTests: XCTestCase { XCTAssertMatch(testFileContents, .contains(#"@Test func example() async throws"#)) XCTAssertNoMatch(testFileContents, .contains("func testExample() throws")) -#if canImport(TestingDisabled) - // Try building it - await XCTAssertBuilds( - path, - buildSystem: .native, - ) - let triple = try UserToolchain.default.targetTriple - XCTAssertFileExists(path.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Modules", "Foo.swiftmodule")) -#endif + #if canImport(TestingDisabled) + // Try building it + await XCTAssertBuilds( + path, + buildSystem: .native, + ) + let triple = try UserToolchain.default.targetTriple + XCTAssertFileExists(path.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Modules", "Foo.swiftmodule")) + #endif } } @@ -248,15 +251,15 @@ final class InitTests: XCTestCase { XCTAssertMatch(testFileContents, .contains(#"@Test func example() async throws"#)) XCTAssertMatch(testFileContents, .contains("func testExample() throws")) -#if canImport(TestingDisabled) - // Try building it - await XCTAssertBuilds( - path, - buildSystem: .native, - ) - let triple = try UserToolchain.default.targetTriple - XCTAssertFileExists(path.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Modules", "Foo.swiftmodule")) -#endif + #if canImport(TestingDisabled) + // Try building it + await XCTAssertBuilds( + path, + buildSystem: .native, + ) + let triple = try UserToolchain.default.targetTriple + XCTAssertFileExists(path.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Modules", "Foo.swiftmodule")) + #endif } } @@ -285,15 +288,15 @@ final class InitTests: XCTestCase { XCTAssertNoSuchPath(path.appending("Tests")) -#if canImport(TestingDisabled) - // Try building it - await XCTAssertBuilds( - path, - buildSystem: .native, - ) - let triple = try UserToolchain.default.targetTriple - XCTAssertFileExists(path.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Modules", "Foo.swiftmodule")) -#endif + #if canImport(TestingDisabled) + // Try building it + await XCTAssertBuilds( + path, + buildSystem: .native, + ) + let triple = try UserToolchain.default.targetTriple + XCTAssertFileExists(path.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Modules", "Foo.swiftmodule")) + #endif } } @@ -377,8 +380,13 @@ final class InitTests: XCTestCase { XCTAssertFileExists(manifest) let manifestContents: String = try localFileSystem.readFileContents(manifest) XCTAssertMatch(manifestContents, .and(.contains(".plugin("), .contains("targets: [\"MyCommandPlugin\"]"))) - XCTAssertMatch(manifestContents, .and(.contains(".plugin("), - .and(.contains("capability: .command(intent: .custom("), .contains("verb: \"MyCommandPlugin\"")))) + XCTAssertMatch( + manifestContents, + .and( + .contains(".plugin("), + .and(.contains("capability: .command(intent: .custom("), .contains("verb: \"MyCommandPlugin\"")) + ) + ) // Check basic content that we expect in the plugin source file let source = path.appending("Plugins", "MyCommandPlugin.swift") @@ -391,7 +399,7 @@ final class InitTests: XCTestCase { XCTAssertMatch(sourceContents, .contains("performCommand(context: XcodePluginContext")) } } - + func testInitPackageBuildToolPlugin() throws { try testWithTemporaryDirectory { tmpPath in let fs = localFileSystem @@ -431,13 +439,13 @@ final class InitTests: XCTestCase { func testInitPackageNonc99Directory() async throws { try await withTemporaryDirectory(removeTreeOnDeinit: true) { tempDirPath in XCTAssertDirectoryExists(tempDirPath) - + // Create a directory with non c99name. let packageRoot = tempDirPath.appending("some-package") let packageName = packageRoot.basename try localFileSystem.createDirectory(packageRoot) XCTAssertDirectoryExists(packageRoot) - + // Create the package let initPackage = try InitPackage( name: packageName, @@ -457,15 +465,15 @@ final class InitTests: XCTestCase { XCTAssertFileExists(packageRoot.appending(components: ".build", triple.platformBuildPathComponent, "debug", "Modules", "some_package.swiftmodule")) } } - + func testNonC99NameExecutablePackage() async throws { try await withTemporaryDirectory(removeTreeOnDeinit: true) { tempDirPath in XCTAssertDirectoryExists(tempDirPath) - + let packageRoot = tempDirPath.appending("Foo") try localFileSystem.createDirectory(packageRoot) XCTAssertDirectoryExists(packageRoot) - + // Create package with non c99name. let initPackage = try InitPackage( name: "package-name", @@ -474,7 +482,7 @@ final class InitTests: XCTestCase { fileSystem: localFileSystem ) try initPackage.writePackageStructure() - + await XCTAssertBuilds( packageRoot, buildSystem: .native, @@ -537,21 +545,21 @@ final class InitTests: XCTestCase { private func packageWithNameOnly(named name: String) -> String { return """ - let package = Package( - name: "\(name)" - ) - """ + let package = Package( + name: "\(name)" + ) + """ } private func packageWithNameAndDependencies(with name: String) -> String { return """ -let package = Package( - name: "\(name)", - dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), - ] -) -""" + let package = Package( + name: "\(name)", + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ] + ) + """ } } diff --git a/Tests/WorkspaceTests/ManifestSourceGenerationTests.swift b/Tests/WorkspaceTests/ManifestSourceGenerationTests.swift index 3f956e0913a..303faa5ca88 100644 --- a/Tests/WorkspaceTests/ManifestSourceGenerationTests.swift +++ b/Tests/WorkspaceTests/ManifestSourceGenerationTests.swift @@ -20,16 +20,16 @@ import XCTest extension String { fileprivate func nativePathString(escaped: Bool) -> String { -#if _runtime(_ObjC) - return self -#else - let fsr = self.fileSystemRepresentation - defer { fsr.deallocate() } - if escaped { - return String(cString: fsr).replacingOccurrences(of: "\\", with: "\\\\") - } - return String(cString: fsr) -#endif + #if _runtime(_ObjC) + return self + #else + let fsr = self.fileSystemRepresentation + defer { fsr.deallocate() } + if escaped { + return String(cString: fsr).replacingOccurrences(of: "\\", with: "\\\\") + } + return String(cString: fsr) + #endif } } @@ -74,7 +74,8 @@ final class ManifestSourceGenerationTests: XCTestCase { let newContents = try manifest.generateManifestFileContents( packageDirectory: packageDir, toolsVersionHeaderComment: toolsVersionHeaderComment, - additionalImportModuleNames: additionalImportModuleNames) + additionalImportModuleNames: additionalImportModuleNames + ) // Check that the tools version was serialized properly. let versionSpacing = (toolsVersion >= .v5_4) ? " " : "" @@ -286,7 +287,7 @@ final class ManifestSourceGenerationTests: XCTestCase { func testPackageDependencyVariations() async throws { try XCTSkipOnWindows( - because:"Intermittently fails", + because: "Intermittently fails", skipPlatformCi: true, ) let manifestContents = """ @@ -517,7 +518,7 @@ final class ManifestSourceGenerationTests: XCTestCase { """ try await testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_9) } - + func testCustomProductSourceGeneration() throws { // Create a manifest containing a product for which we'd like to do custom source fragment generation. let packageDir = AbsolutePath("/tmp/MyLibrary") @@ -535,24 +536,26 @@ final class ManifestSourceGenerationTests: XCTestCase { ) // Generate the manifest contents, using a custom source generator for the product type. - let contents = manifest.generateManifestFileContents(packageDirectory: packageDir, customProductTypeSourceGenerator: { product in - // This example handles library types in a custom way, for testing purposes. - var params: [SourceCodeFragment] = [] - params.append(SourceCodeFragment(key: "name", string: product.name)) - if !product.targets.isEmpty { - params.append(SourceCodeFragment(key: "targets", strings: product.targets)) - } - // Handle .library specially (by not emitting as multiline), otherwise asking for default behavior. - if case .library(let type) = product.type { - if type != .automatic { - params.append(SourceCodeFragment(key: "type", enum: type.rawValue)) + let contents = manifest.generateManifestFileContents( + packageDirectory: packageDir, + customProductTypeSourceGenerator: { product in + // This example handles library types in a custom way, for testing purposes. + var params: [SourceCodeFragment] = [] + params.append(SourceCodeFragment(key: "name", string: product.name)) + if !product.targets.isEmpty { + params.append(SourceCodeFragment(key: "targets", strings: product.targets)) + } + // Handle .library specially (by not emitting as multiline), otherwise asking for default behavior. + if case .library(let type) = product.type { + if type != .automatic { + params.append(SourceCodeFragment(key: "type", enum: type.rawValue)) + } + return SourceCodeFragment(enum: "library", subnodes: params, multiline: false) + } else { + return nil } - return SourceCodeFragment(enum: "library", subnodes: params, multiline: false) - } - else { - return nil } - }) + ) // Check that we generated what we expected. XCTAssertTrue(contents.contains(".library(name: \"Foo\", targets: [\"Bar\"], type: .static)"), "contents: \(contents)") @@ -560,179 +563,179 @@ final class ManifestSourceGenerationTests: XCTestCase { /// Tests a fully customized iOSApplication (one that exercises every parameter in at least some way). func testAppleProductSettings() throws { - #if ENABLE_APPLE_PRODUCT_TYPES - let manifestContents = """ - // swift-tools-version: 999.0 - import PackageDescription - let package = Package( - name: "Foo", - products: [ - .iOSApplication( - name: "Foo", - targets: ["Foo"], - bundleIdentifier: "com.my.app", - teamIdentifier: "ZXYTEAM123", - displayVersion: "1.4.2 Extra Cool", - bundleVersion: "1.4.2", - appIcon: .placeholder(icon: .cloud), - accentColor: .presetColor(.red), - supportedDeviceFamilies: [.phone, .pad, .mac], - supportedInterfaceOrientations: [ - .portrait, - .landscapeRight(), - .landscapeLeft(.when(deviceFamilies: [.mac])) - ], - capabilities: [ - .camera(purposeString: "All the better to see you with…", .when(deviceFamilies: [.pad, .phone])), - .fileAccess(.userSelectedFiles, mode: .readOnly, .when(deviceFamilies: [.mac])), - .fileAccess(.pictureFolder, mode: .readWrite, .when(deviceFamilies: [.mac])), - .fileAccess(.musicFolder, mode: .readOnly), - .fileAccess(.downloadsFolder, mode: .readWrite, .when(deviceFamilies: [.mac])), - .fileAccess(.moviesFolder, mode: .readWrite, .when(deviceFamilies: [.mac])), - .incomingNetworkConnections(.when(deviceFamilies: [.mac])), - .outgoingNetworkConnections(), - .microphone(purposeString: "All the better to hear you with…"), - .motion(purposeString: "Move along, move along, …"), - .localNetwork( - purposeString: "Communication is key…", - bonjourServiceTypes: ["_ipp._tcp", "_ipps._tcp"], - .when(deviceFamilies: [.mac]) - ), - .appTransportSecurity( - configuration: .init( - allowsArbitraryLoadsInWebContent: true, - allowsArbitraryLoadsForMedia: false, - allowsLocalNetworking: false, - exceptionDomains: [ - .init( - domainName: "not-shady-at-all-domain.biz", - includesSubdomains: true, - exceptionAllowsInsecureHTTPLoads: true, - exceptionMinimumTLSVersion: "2", - exceptionRequiresForwardSecrecy: false, - requiresCertificateTransparency: false - ) - ], - pinnedDomains: [ - .init( - domainName: "honest-harrys-pinned-domain.biz", - includesSubdomains : false, - pinnedCAIdentities : [["a": "b", "x": "y"], [:]], - pinnedLeafIdentities : [["v": "w"]] - ) - ] + #if ENABLE_APPLE_PRODUCT_TYPES + let manifestContents = """ + // swift-tools-version: 999.0 + import PackageDescription + let package = Package( + name: "Foo", + products: [ + .iOSApplication( + name: "Foo", + targets: ["Foo"], + bundleIdentifier: "com.my.app", + teamIdentifier: "ZXYTEAM123", + displayVersion: "1.4.2 Extra Cool", + bundleVersion: "1.4.2", + appIcon: .placeholder(icon: .cloud), + accentColor: .presetColor(.red), + supportedDeviceFamilies: [.phone, .pad, .mac], + supportedInterfaceOrientations: [ + .portrait, + .landscapeRight(), + .landscapeLeft(.when(deviceFamilies: [.mac])) + ], + capabilities: [ + .camera(purposeString: "All the better to see you with…", .when(deviceFamilies: [.pad, .phone])), + .fileAccess(.userSelectedFiles, mode: .readOnly, .when(deviceFamilies: [.mac])), + .fileAccess(.pictureFolder, mode: .readWrite, .when(deviceFamilies: [.mac])), + .fileAccess(.musicFolder, mode: .readOnly), + .fileAccess(.downloadsFolder, mode: .readWrite, .when(deviceFamilies: [.mac])), + .fileAccess(.moviesFolder, mode: .readWrite, .when(deviceFamilies: [.mac])), + .incomingNetworkConnections(.when(deviceFamilies: [.mac])), + .outgoingNetworkConnections(), + .microphone(purposeString: "All the better to hear you with…"), + .motion(purposeString: "Move along, move along, …"), + .localNetwork( + purposeString: "Communication is key…", + bonjourServiceTypes: ["_ipp._tcp", "_ipps._tcp"], + .when(deviceFamilies: [.mac]) ), - .when(deviceFamilies: [.phone, .pad]) - ) - ], - appCategory: .weather, - additionalInfoPlistContentFilePath: "some/path/to/a/file.plist" - ), - ], - targets: [ - .executableTarget( - name: "Foo" - ), - ] - ) - """ - try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_5) - #else - throw XCTSkip("ENABLE_APPLE_PRODUCT_TYPES is not set") - #endif + .appTransportSecurity( + configuration: .init( + allowsArbitraryLoadsInWebContent: true, + allowsArbitraryLoadsForMedia: false, + allowsLocalNetworking: false, + exceptionDomains: [ + .init( + domainName: "not-shady-at-all-domain.biz", + includesSubdomains: true, + exceptionAllowsInsecureHTTPLoads: true, + exceptionMinimumTLSVersion: "2", + exceptionRequiresForwardSecrecy: false, + requiresCertificateTransparency: false + ) + ], + pinnedDomains: [ + .init( + domainName: "honest-harrys-pinned-domain.biz", + includesSubdomains : false, + pinnedCAIdentities : [["a": "b", "x": "y"], [:]], + pinnedLeafIdentities : [["v": "w"]] + ) + ] + ), + .when(deviceFamilies: [.phone, .pad]) + ) + ], + appCategory: .weather, + additionalInfoPlistContentFilePath: "some/path/to/a/file.plist" + ), + ], + targets: [ + .executableTarget( + name: "Foo" + ), + ] + ) + """ + try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_5) + #else + throw XCTSkip("ENABLE_APPLE_PRODUCT_TYPES is not set") + #endif } /// Tests loading an iOSApplication product configured with the `.asset(_)` variant of the /// appIcon and accentColor parameters. func testAssetBasedAccentColorAndAppIconAppleProductSettings() throws { - #if ENABLE_APPLE_PRODUCT_TYPES - let manifestContents = """ - // swift-tools-version: 999.0 - import PackageDescription - let package = Package( - name: "Foo", - products: [ - .iOSApplication( - name: "Foo", - targets: ["Foo"], - appIcon: .asset("AppIcon"), - accentColor: .asset("AccentColor") - ), - ], - targets: [ - .executableTarget( - name: "Foo" - ), - ] - ) - """ - try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_5) - #else - throw XCTSkip("ENABLE_APPLE_PRODUCT_TYPES is not set") - #endif + #if ENABLE_APPLE_PRODUCT_TYPES + let manifestContents = """ + // swift-tools-version: 999.0 + import PackageDescription + let package = Package( + name: "Foo", + products: [ + .iOSApplication( + name: "Foo", + targets: ["Foo"], + appIcon: .asset("AppIcon"), + accentColor: .asset("AccentColor") + ), + ], + targets: [ + .executableTarget( + name: "Foo" + ), + ] + ) + """ + try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_5) + #else + throw XCTSkip("ENABLE_APPLE_PRODUCT_TYPES is not set") + #endif } /// Tests loading an iOSApplication product configured with legacy 'iconAssetName' and 'accentColorAssetName' parameters. func testLegacyAccentColorAndAppIconAppleProductSettings() throws { - #if ENABLE_APPLE_PRODUCT_TYPES - let manifestContents = """ - // swift-tools-version: 999.0 - import PackageDescription - let package = Package( - name: "Foo", - products: [ - .iOSApplication( - name: "Foo", - targets: ["Foo"], - iconAssetName: "icon", - accentColorAssetName: "accentColor" - ), - ], - targets: [ - .executableTarget( - name: "Foo" - ), - ] - ) - """ - try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_5) - #else - throw XCTSkip("ENABLE_APPLE_PRODUCT_TYPES is not set") - #endif + #if ENABLE_APPLE_PRODUCT_TYPES + let manifestContents = """ + // swift-tools-version: 999.0 + import PackageDescription + let package = Package( + name: "Foo", + products: [ + .iOSApplication( + name: "Foo", + targets: ["Foo"], + iconAssetName: "icon", + accentColorAssetName: "accentColor" + ), + ], + targets: [ + .executableTarget( + name: "Foo" + ), + ] + ) + """ + try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_5) + #else + throw XCTSkip("ENABLE_APPLE_PRODUCT_TYPES is not set") + #endif } /// Tests the smallest allowed iOSApplication (one that has default values for everything not required). Make sure no defaults get added to it. func testMinimalAppleProductSettings() throws { - #if ENABLE_APPLE_PRODUCT_TYPES - let manifestContents = """ - // swift-tools-version: 999.0 - import PackageDescription - let package = Package( - name: "Foo", - products: [ - .iOSApplication( - name: "Foo", - targets: ["Foo"], - accentColor: .asset("AccentColor"), - supportedDeviceFamilies: [ - .mac - ], - supportedInterfaceOrientations: [ - .portrait - ] - ), - ], - targets: [ - .executableTarget( - name: "Foo" - ), - ] - ) - """ - try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_5) - #else - throw XCTSkip("ENABLE_APPLE_PRODUCT_TYPES is not set") - #endif + #if ENABLE_APPLE_PRODUCT_TYPES + let manifestContents = """ + // swift-tools-version: 999.0 + import PackageDescription + let package = Package( + name: "Foo", + products: [ + .iOSApplication( + name: "Foo", + targets: ["Foo"], + accentColor: .asset("AccentColor"), + supportedDeviceFamilies: [ + .mac + ], + supportedInterfaceOrientations: [ + .portrait + ] + ), + ], + targets: [ + .executableTarget( + name: "Foo" + ), + ] + ) + """ + try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_5) + #else + throw XCTSkip("ENABLE_APPLE_PRODUCT_TYPES is not set") + #endif } func testModuleAliasGeneration() async throws { @@ -745,32 +748,38 @@ final class ManifestSourceGenerationTests: XCTestCase { .localSourceControl(path: "/barPkg", requirement: .upToNextMajor(from: "2.0.0")), ], targets: [ - try TargetDescription(name: "exe", - dependencies: ["Logging", - .product(name: "Foo", - package: "fooPkg", - moduleAliases: ["Logging": "FooLogging"] - ), - .product(name: "Bar", - package: "barPkg", - moduleAliases: ["Logging": "BarLogging"] - ) - ]), + try TargetDescription( + name: "exe", + dependencies: [ + "Logging", + .product( + name: "Foo", + package: "fooPkg", + moduleAliases: ["Logging": "FooLogging"] + ), + .product( + name: "Bar", + package: "barPkg", + moduleAliases: ["Logging": "BarLogging"] + ), + ] + ), try TargetDescription(name: "Logging", dependencies: []), - ]) + ] + ) let contents = try manifest.generateManifestFileContents(packageDirectory: manifest.path.parentDirectory) let parts = - """ - dependencies: [ - "Logging", - .product(name: "Foo", package: "fooPkg", moduleAliases: [ - "Logging": "FooLogging" - ]), - .product(name: "Bar", package: "barPkg", moduleAliases: [ - "Logging": "BarLogging" - ]) - ] - """ + """ + dependencies: [ + "Logging", + .product(name: "Foo", package: "fooPkg", moduleAliases: [ + "Logging": "FooLogging" + ]), + .product(name: "Bar", package: "barPkg", moduleAliases: [ + "Logging": "BarLogging" + ]) + ] + """ let trimmedContents = contents.components(separatedBy: CharacterSet.whitespacesAndNewlines) let trimmedParts = parts.components(separatedBy: CharacterSet.whitespacesAndNewlines) let isContained = trimmedParts.allSatisfy(trimmedContents.contains(_:)) @@ -831,7 +840,8 @@ final class ManifestSourceGenerationTests: XCTestCase { dependencies: [], targets: [ try TargetDescription(name: "MyPlugin", type: .plugin, pluginCapability: .command(intent: .custom(verb: "foo", description: "bar"), permissions: [.allowNetworkConnections(scope: .all(ports: [23, 42, 443, 8080]), reason: "internet good")])) - ]) + ] + ) let contents = try manifest.generateManifestFileContents(packageDirectory: manifest.path.parentDirectory) try await testManifestWritingRoundTrip(manifestContents: contents, toolsVersion: .v5_9) } @@ -862,10 +872,11 @@ final class ManifestSourceGenerationTests: XCTestCase { type: .executable, settings: [ .init(tool: .swift, kind: .swiftLanguageMode(.v5), condition: .init(platformNames: ["linux"])), - .init(tool: .swift, kind: .swiftLanguageMode(.v4), condition: .init(platformNames: ["macos"], config: "debug")) + .init(tool: .swift, kind: .swiftLanguageMode(.v4), condition: .init(platformNames: ["macos"], config: "debug")), ] - ) - ]) + ), + ] + ) let contents = try manifest.generateManifestFileContents(packageDirectory: manifest.path.parentDirectory) try await testManifestWritingRoundTrip(manifestContents: contents, toolsVersion: .v6_0) } @@ -910,7 +921,8 @@ final class ManifestSourceGenerationTests: XCTestCase { .init(tool: .cxx, kind: .treatWarning("deprecated-declarations", .warning), condition: .init(config: "debug")), ] ), - ]) + ] + ) let contents = try manifest.generateManifestFileContents(packageDirectory: manifest.path.parentDirectory) try await testManifestWritingRoundTrip(manifestContents: contents, toolsVersion: .v6_2) } @@ -943,10 +955,11 @@ final class ManifestSourceGenerationTests: XCTestCase { type: .executable, settings: [ .init(tool: .swift, kind: .defaultIsolation(.nonisolated), condition: .init(platformNames: ["linux"])), - .init(tool: .swift, kind: .defaultIsolation(.MainActor), condition: .init(platformNames: ["macos"], config: "debug")) + .init(tool: .swift, kind: .defaultIsolation(.MainActor), condition: .init(platformNames: ["macos"], config: "debug")), ] - ) - ]) + ), + ] + ) let contents = try manifest.generateManifestFileContents(packageDirectory: manifest.path.parentDirectory) try await testManifestWritingRoundTrip(manifestContents: contents, toolsVersion: .v6_2) } diff --git a/Tests/WorkspaceTests/MirrorsConfigurationTests.swift b/Tests/WorkspaceTests/MirrorsConfigurationTests.swift index 7d584bcab17..7784b5c7c12 100644 --- a/Tests/WorkspaceTests/MirrorsConfigurationTests.swift +++ b/Tests/WorkspaceTests/MirrorsConfigurationTests.swift @@ -28,16 +28,16 @@ fileprivate struct MirrorsConfigurationTests { try fs.writeFileContents( configFile, string: """ - { - "object": [ { - "mirror": "\(mirrorURL)", - "original": "\(originalURL)" + "object": [ + { + "mirror": "\(mirrorURL)", + "original": "\(originalURL)" + } + ], + "version": 1 } - ], - "version": 1 - } - """ + """ ) let config = Workspace.Configuration.MirrorsStorage(path: configFile, fileSystem: fs, deleteWhenEmpty: true) @@ -68,18 +68,18 @@ fileprivate struct MirrorsConfigurationTests { let config = Workspace.Configuration.MirrorsStorage(path: configFile, fileSystem: fs, deleteWhenEmpty: true) - try config.apply{ _ in } + try config.apply { _ in } #expect(!fs.exists(configFile)) let originalURL = "https://github.com/apple/swift-argument-parser.git" let mirrorURL = "https://github.com/mona/swift-argument-parser.git" - try config.apply{ mirrors in + try config.apply { mirrors in try mirrors.set(mirror: mirrorURL, for: originalURL) } #expect(fs.exists(configFile)) - try config.apply{ mirrors in + try config.apply { mirrors in try mirrors.unset(originalOrMirror: originalURL) } #expect(!fs.exists(configFile)) @@ -92,18 +92,18 @@ fileprivate struct MirrorsConfigurationTests { let config = Workspace.Configuration.MirrorsStorage(path: configFile, fileSystem: fs, deleteWhenEmpty: false) - try config.apply{ _ in } + try config.apply { _ in } #expect(!fs.exists(configFile)) let originalURL = "https://github.com/apple/swift-argument-parser.git" let mirrorURL = "https://github.com/mona/swift-argument-parser.git" - try config.apply{ mirrors in + try config.apply { mirrors in try mirrors.set(mirror: mirrorURL, for: originalURL) } #expect(fs.exists(configFile)) - try config.apply{ mirrors in + try config.apply { mirrors in try mirrors.unset(originalOrMirror: originalURL) } #expect(fs.exists(configFile)) diff --git a/Tests/WorkspaceTests/PrebuiltsTests.swift b/Tests/WorkspaceTests/PrebuiltsTests.swift index 759e94c3721..496d93ac9b9 100644 --- a/Tests/WorkspaceTests/PrebuiltsTests.swift +++ b/Tests/WorkspaceTests/PrebuiltsTests.swift @@ -43,7 +43,7 @@ final class PrebuiltsTests: XCTestCase { products: [ "SwiftSyntaxMacrosTestSupport", "SwiftCompilerPlugin", - "SwiftSyntaxMacros" + "SwiftSyntaxMacros", ], cModules: [ "_SwiftSyntaxCShims" @@ -337,7 +337,10 @@ final class PrebuiltsTests: XCTestCase { let artifact = Data() try await with(fileSystem: fs, artifact: artifact, swiftSyntaxVersion: "600.0.1", swiftSyntaxURL: "git@github.com:swiftlang/swift-syntax.git") { - manifest, rootCertPath, rootPackage, swiftSyntax in + manifest, + rootCertPath, + rootPackage, + swiftSyntax in let manifestData = try JSONEncoder().encode(manifest) @@ -399,7 +402,10 @@ final class PrebuiltsTests: XCTestCase { let artifact = Data() try await with(fileSystem: fs, artifact: artifact, swiftSyntaxVersion: "600.0.1", swiftSyntaxURL: "https://github.com/apple/swift-syntax.git") { - manifest, rootCertPath, rootPackage, swiftSyntax in + manifest, + rootCertPath, + rootPackage, + swiftSyntax in let manifestData = try JSONEncoder().encode(manifest) @@ -524,7 +530,7 @@ final class PrebuiltsTests: XCTestCase { try await with(fileSystem: fs, artifact: artifact, swiftSyntaxVersion: "600.0.2") { _, rootCertPath, rootPackage, swiftSyntax in let secondFetch = SendableBox(false) - + let httpClient = HTTPClient { request, progressHandler in if request.url == "https://download.swift.org/prebuilts/swift-syntax/600.0.2/\(self.swiftVersion)-manifest.json" { let secondFetch = await secondFetch.value @@ -535,12 +541,12 @@ final class PrebuiltsTests: XCTestCase { return .notFound() } } - + let archiver = MockArchiver(handler: { _, archivePath, destination, completion in XCTFail("Unexpected call to archiver") completion(.success(())) }) - + let workspace = try await MockWorkspace( sandbox: sandbox, fileSystem: fs, @@ -557,7 +563,7 @@ final class PrebuiltsTests: XCTestCase { rootCertPath: rootCertPath ) ) - + try await workspace.checkPackageGraph(roots: ["Foo"]) { modulesGraph, diagnostics in XCTAssertTrue(diagnostics.filter({ $0.severity == .error }).isEmpty) let rootPackage = try XCTUnwrap(modulesGraph.rootPackages.first) @@ -566,9 +572,9 @@ final class PrebuiltsTests: XCTestCase { try checkSettings(rootPackage, "Foo", usePrebuilt: false) try checkSettings(rootPackage, "FooClient", usePrebuilt: false) } - + await secondFetch.set(true) - + try await workspace.checkPackageGraph(roots: ["Foo"]) { modulesGraph, diagnostics in XCTAssertTrue(diagnostics.filter({ $0.severity == .error }).isEmpty) let rootPackage = try XCTUnwrap(modulesGraph.rootPackages.first) @@ -952,7 +958,7 @@ final class PrebuiltsTests: XCTestCase { swiftSyntax ] ) - + try await workspace.checkPackageGraph(roots: ["Foo"]) { modulesGraph, diagnostics in XCTAssertTrue(diagnostics.filter({ $0.severity == .error }).isEmpty) let rootPackage = try XCTUnwrap(modulesGraph.rootPackages.first) @@ -968,9 +974,9 @@ final class PrebuiltsTests: XCTestCase { extension String { var fixwin: String { #if os(Windows) - return self.replacingOccurrences(of: "/", with: "\\") + return self.replacingOccurrences(of: "/", with: "\\") #else - return self + return self #endif } } diff --git a/Tests/WorkspaceTests/RegistryPackageContainerTests.swift b/Tests/WorkspaceTests/RegistryPackageContainerTests.swift index d7eb6a20461..2766b700f16 100644 --- a/Tests/WorkspaceTests/RegistryPackageContainerTests.swift +++ b/Tests/WorkspaceTests/RegistryPackageContainerTests.swift @@ -46,17 +46,17 @@ final class RegistryPackageContainerTests: XCTestCase { releasesRequestHandler: { request, _ in let metadata = RegistryClient.Serialization.PackageMetadata( releases: [ - "1.0.0": .init(url: .none, problem: .none), - "1.0.1": .init(url: .none, problem: .none), - "1.0.2": .init(url: .none, problem: .none), - "1.0.3": .init(url: .none, problem: .none) + "1.0.0": .init(url: .none, problem: .none), + "1.0.1": .init(url: .none, problem: .none), + "1.0.2": .init(url: .none, problem: .none), + "1.0.3": .init(url: .none, problem: .none), ] ) return HTTPClientResponse( statusCode: 200, headers: [ "Content-Version": "1", - "Content-Type": "application/json" + "Content-Type": "application/json", ], body: try! JSONEncoder.makeWithDefaults().encode(metadata) ) @@ -79,7 +79,7 @@ final class RegistryPackageContainerTests: XCTestCase { statusCode: 200, headers: [ "Content-Version": "1", - "Content-Type": "text/x-swift" + "Content-Type": "text/x-swift", ], body: Data("// swift-tools-version:\(toolsVersion)".utf8) ) @@ -145,7 +145,7 @@ final class RegistryPackageContainerTests: XCTestCase { "Link": """ \(self.manifestLink(packageIdentity, .v5_4)), \(self.manifestLink(packageIdentity, .v5_5)), - """ + """, ], body: Data("// swift-tools-version:\(ToolsVersion.v5_3)".utf8) ) @@ -164,7 +164,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5_2) // the version of the alternate + let provider = try createProvider(.v5_2) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) let version = try await container.toolsVersion(for: packageVersion) @@ -174,7 +174,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5_3) // the version of the alternate + let provider = try createProvider(.v5_3) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) let version = try await container.toolsVersion(for: packageVersion) @@ -184,7 +184,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5_4) // the version of the alternate + let provider = try createProvider(.v5_4) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) let version = try await container.toolsVersion(for: packageVersion) @@ -194,7 +194,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5_5) // the version of the alternate + let provider = try createProvider(.v5_5) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) let version = try await container.toolsVersion(for: packageVersion) @@ -204,7 +204,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5_6) // the version of the alternate + let provider = try createProvider(.v5_6) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) let version = try await container.toolsVersion(for: packageVersion) @@ -233,7 +233,7 @@ final class RegistryPackageContainerTests: XCTestCase { fileSystem: fs, manifestRequestHandler: { request, _ in let requestedVersionString = request.url.query?.spm_dropPrefix("swift-version=") - let requestedVersion = (requestedVersionString.flatMap{ ToolsVersion(string: $0) }) ?? .v5_3 + let requestedVersion = (requestedVersionString.flatMap { ToolsVersion(string: $0) }) ?? .v5_3 guard supportedVersions.contains(requestedVersion) else { throw StringError("invalid version \(requestedVersion)") } @@ -244,7 +244,7 @@ final class RegistryPackageContainerTests: XCTestCase { "Content-Type": "text/x-swift", "Link": (supportedVersions.subtracting([requestedVersion])).map { self.manifestLink(packageIdentity, $0) - }.joined(separator: ",\n") + }.joined(separator: ",\n"), ], body: Data("// swift-tools-version:\(requestedVersion)".utf8) ) @@ -292,7 +292,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5_3) // the version of the alternate + let provider = try createProvider(.v5_3) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) as! RegistryPackageContainer let manifest = try await container.loadManifest(version: packageVersion) @@ -300,7 +300,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(v5_3_3) // the version of the alternate + let provider = try createProvider(v5_3_3) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) as! RegistryPackageContainer let manifest = try await container.loadManifest(version: packageVersion) @@ -308,7 +308,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5_4) // the version of the alternate + let provider = try createProvider(.v5_4) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) as! RegistryPackageContainer let manifest = try await container.loadManifest(version: packageVersion) @@ -316,7 +316,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5_5) // the version of the alternate + let provider = try createProvider(.v5_5) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) as! RegistryPackageContainer let manifest = try await container.loadManifest(version: packageVersion) @@ -324,7 +324,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5_6) // the version of the alternate + let provider = try createProvider(.v5_6) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) as! RegistryPackageContainer let manifest = try await container.loadManifest(version: packageVersion) @@ -332,7 +332,7 @@ final class RegistryPackageContainerTests: XCTestCase { } do { - let provider = try createProvider(.v5) // the version of the alternate + let provider = try createProvider(.v5) // the version of the alternate let ref = PackageReference.registry(identity: packageIdentity) let container = try await provider.getContainer(for: ref) as! RegistryPackageContainer let manifest = try await container.loadManifest(version: packageVersion) @@ -365,82 +365,89 @@ final class RegistryPackageContainerTests: XCTestCase { configuration!.defaultRegistry = .init(url: "http://localhost", supportsAvailability: false) } - let releasesRequestHandler = releasesRequestHandler ?? { request, _ in - let metadata = RegistryClient.Serialization.PackageMetadata( - releases: [packageVersion.description: .init(url: .none, problem: .none)] - ) - return HTTPClientResponse( - statusCode: 200, - headers: [ - "Content-Version": "1", - "Content-Type": "application/json" - ], - body: try! jsonEncoder.encode(metadata) - ) - } - - let versionMetadataRequestHandler = versionMetadataRequestHandler ?? { request, _ in - let metadata = RegistryClient.Serialization.VersionMetadata( - id: packageIdentity.description, - version: packageVersion.description, - resources: [ - .init( - name: "source-archive", - type: "application/zip", - checksum: "", - signing: nil - ) - ], - metadata: .init(description: ""), - publishedAt: nil - ) - return HTTPClientResponse( - statusCode: 200, - headers: [ - "Content-Version": "1", - "Content-Type": "application/json" - ], - body: try! jsonEncoder.encode(metadata) - ) - } + let releasesRequestHandler = + releasesRequestHandler ?? { request, _ in + let metadata = RegistryClient.Serialization.PackageMetadata( + releases: [packageVersion.description: .init(url: .none, problem: .none)] + ) + return HTTPClientResponse( + statusCode: 200, + headers: [ + "Content-Version": "1", + "Content-Type": "application/json", + ], + body: try! jsonEncoder.encode(metadata) + ) + } - let manifestRequestHandler = manifestRequestHandler ?? { request, _ in - return HTTPClientResponse( - statusCode: 200, - headers: [ - "Content-Version": "1", - "Content-Type": "text/x-swift" - ], - body: Data("// swift-tools-version:\(ToolsVersion.current)".utf8) - ) - } + let versionMetadataRequestHandler = + versionMetadataRequestHandler ?? { request, _ in + let metadata = RegistryClient.Serialization.VersionMetadata( + id: packageIdentity.description, + version: packageVersion.description, + resources: [ + .init( + name: "source-archive", + type: "application/zip", + checksum: "", + signing: nil + ) + ], + metadata: .init(description: ""), + publishedAt: nil + ) + return HTTPClientResponse( + statusCode: 200, + headers: [ + "Content-Version": "1", + "Content-Type": "application/json", + ], + body: try! jsonEncoder.encode(metadata) + ) + } - let downloadArchiveRequestHandler = downloadArchiveRequestHandler ?? { request, _ in - // meh - let path = packagePath - .appending(components: ".build", "registry", "downloads", registryIdentity.scope.description, registryIdentity.name.description) - .appending("\(packageVersion).zip") - try! fileSystem.createDirectory(path.parentDirectory, recursive: true) - try! fileSystem.writeFileContents(path, string: "") - - return HTTPClientResponse( - statusCode: 200, - headers: [ - "Content-Version": "1", - "Content-Type": "application/zip" - ], - body: Data("".utf8) - ) - } + let manifestRequestHandler = + manifestRequestHandler ?? { request, _ in + return HTTPClientResponse( + statusCode: 200, + headers: [ + "Content-Version": "1", + "Content-Type": "text/x-swift", + ], + body: Data("// swift-tools-version:\(ToolsVersion.current)".utf8) + ) + } - let archiver = archiver ?? MockArchiver(handler: { archiver, from, to, completion in - do { - try fileSystem.createDirectory(to.appending("top"), recursive: true) - completion(.success(())) - } catch { - completion(.failure(error)) + let downloadArchiveRequestHandler = + downloadArchiveRequestHandler ?? { request, _ in + // meh + let path = + packagePath + .appending(components: ".build", "registry", "downloads", registryIdentity.scope.description, registryIdentity.name.description) + .appending("\(packageVersion).zip") + try! fileSystem.createDirectory(path.parentDirectory, recursive: true) + try! fileSystem.writeFileContents(path, string: "") + + return HTTPClientResponse( + statusCode: 200, + headers: [ + "Content-Version": "1", + "Content-Type": "application/zip", + ], + body: Data("".utf8) + ) } - }) + + let archiver = + archiver + ?? MockArchiver(handler: { archiver, from, to, completion in + do { + try fileSystem.createDirectory(to.appending("top"), recursive: true) + completion(.success(())) + } catch { + completion(.failure(error)) + } + }) return RegistryClient( configuration: configuration!, @@ -450,34 +457,37 @@ final class RegistryPackageContainerTests: XCTestCase { signingEntityStorage: .none, signingEntityCheckingMode: .strict, authorizationProvider: .none, - customHTTPClient: HTTPClient(configuration: .init(), implementation: { request, progress in - var pathComponents = request.url.pathComponents - if pathComponents.first == "/" { - pathComponents = Array(pathComponents.dropFirst()) - } - guard pathComponents.count >= 2 else { - throw StringError("invalid url \(request.url)") - } - guard pathComponents[0] == registryIdentity.scope.description else { - throw StringError("invalid url \(request.url)") - } - guard pathComponents[1] == registryIdentity.name.description else { - throw StringError("invalid url \(request.url)") - } + customHTTPClient: HTTPClient( + configuration: .init(), + implementation: { request, progress in + var pathComponents = request.url.pathComponents + if pathComponents.first == "/" { + pathComponents = Array(pathComponents.dropFirst()) + } + guard pathComponents.count >= 2 else { + throw StringError("invalid url \(request.url)") + } + guard pathComponents[0] == registryIdentity.scope.description else { + throw StringError("invalid url \(request.url)") + } + guard pathComponents[1] == registryIdentity.name.description else { + throw StringError("invalid url \(request.url)") + } - switch pathComponents.count { - case 2: - return try await releasesRequestHandler(request, progress) - case 3 where pathComponents[2].hasSuffix(".zip"): - return try await downloadArchiveRequestHandler(request, progress) - case 3: - return try await versionMetadataRequestHandler(request, progress) - case 4 where pathComponents[3].hasSuffix(".swift"): - return try await manifestRequestHandler(request, progress) - default: - throw StringError("unexpected url \(request.url)") + switch pathComponents.count { + case 2: + return try await releasesRequestHandler(request, progress) + case 3 where pathComponents[2].hasSuffix(".zip"): + return try await downloadArchiveRequestHandler(request, progress) + case 3: + return try await versionMetadataRequestHandler(request, progress) + case 4 where pathComponents[3].hasSuffix(".swift"): + return try await manifestRequestHandler(request, progress) + default: + throw StringError("unexpected url \(request.url)") + } } - }), + ), customArchiverProvider: { _ in archiver }, delegate: .none, checksumAlgorithm: MockHashAlgorithm() @@ -488,13 +498,14 @@ final class RegistryPackageContainerTests: XCTestCase { guard let registryIdentity = identity.registry else { preconditionFailure("invalid registry identity: '\(identity)'") } - let versionString = if version.patch == 0 && version.minor == 0 { - "\(version.major)" - } else if version.patch == 0 { - "\(version.major).\(version.minor)" - } else { - version.description - } + let versionString = + if version.patch == 0 && version.minor == 0 { + "\(version.major)" + } else if version.patch == 0 { + "\(version.major).\(version.minor)" + } else { + version.description + } return "; rel=\"alternate\"; filename=\"\(Manifest.basename)@swift-\(versionString).swift\"; swift-tools-version=\"\(version)\"" } } diff --git a/Tests/WorkspaceTests/ResolvedPackagesStoreTests.swift b/Tests/WorkspaceTests/ResolvedPackagesStoreTests.swift index e0e27681123..5f12bddd2bd 100644 --- a/Tests/WorkspaceTests/ResolvedPackagesStoreTests.swift +++ b/Tests/WorkspaceTests/ResolvedPackagesStoreTests.swift @@ -38,7 +38,7 @@ final class ResolvedPackagesStoreTests: XCTestCase { let barRef = PackageReference.localSourceControl(identity: bar, path: barPath) var store = try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fs, mirrors: .init()) - + // `Package.resolved` file should not be created right now. XCTAssert(!fs.exists(packageResolvedFile)) XCTAssert(store.resolvedPackages.isEmpty) @@ -139,7 +139,7 @@ final class ResolvedPackagesStoreTests: XCTestCase { // Test registry resolution. do { - let identity = PackageIdentity.plain("baz.baz") // FIXME: use scope identifier + let identity = PackageIdentity.plain("baz.baz") // FIXME: use scope identifier var store = try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fs, mirrors: .init()) store.track( @@ -159,34 +159,36 @@ final class ResolvedPackagesStoreTests: XCTestCase { let fs = InMemoryFileSystem() let packageResolvedFile = AbsolutePath("/Package.resolved") - try fs.writeFileContents(packageResolvedFile, string: - """ - { - "version": 1, - "object": { - "pins": [ - { - "package": "Clang_C", - "repositoryURL": "https://github.com/something/Clang_C.git", - "state": { - "branch": null, - "revision": "90a9574276f0fd17f02f58979423c3fd4d73b59e", - "version": "1.0.2", - } - }, - { - "package": "Commandant", - "repositoryURL": "https://github.com/something/Commandant.git", - "state": { - "branch": null, - "revision": "c281992c31c3f41c48b5036c5a38185eaec32626", - "version": "0.12.0" - } + try fs.writeFileContents( + packageResolvedFile, + string: + """ + { + "version": 1, + "object": { + "pins": [ + { + "package": "Clang_C", + "repositoryURL": "https://github.com/something/Clang_C.git", + "state": { + "branch": null, + "revision": "90a9574276f0fd17f02f58979423c3fd4d73b59e", + "version": "1.0.2", + } + }, + { + "package": "Commandant", + "repositoryURL": "https://github.com/something/Commandant.git", + "state": { + "branch": null, + "revision": "c281992c31c3f41c48b5036c5a38185eaec32626", + "version": "0.12.0" + } + } + ] } - ] - } - } - """ + } + """ ) let store = try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fs, mirrors: .init()) @@ -197,40 +199,42 @@ final class ResolvedPackagesStoreTests: XCTestCase { let fs = InMemoryFileSystem() let packageResolvedFile = AbsolutePath("/Package.resolved") - try fs.writeFileContents(packageResolvedFile, string: - """ - { - "version": 2, - "pins": [ - { - "identity": "clang_c", - "kind": "remoteSourceControl", - "location": "https://github.com/something/Clang_C.git", - "state": { - "revision": "90a9574276f0fd17f02f58979423c3fd4d73b59e", - "version": "1.0.2", - } - }, - { - "identity": "commandant", - "kind": "remoteSourceControl", - "location": "https://github.com/something/Commandant.git", - "state": { - "revision": "c281992c31c3f41c48b5036c5a38185eaec32626", - "version": "0.12.0" - } - }, - { - "identity": "scope.package", - "kind": "registry", - "location": "", - "state": { - "version": "0.12.0" - } - } - ] - } - """ + try fs.writeFileContents( + packageResolvedFile, + string: + """ + { + "version": 2, + "pins": [ + { + "identity": "clang_c", + "kind": "remoteSourceControl", + "location": "https://github.com/something/Clang_C.git", + "state": { + "revision": "90a9574276f0fd17f02f58979423c3fd4d73b59e", + "version": "1.0.2", + } + }, + { + "identity": "commandant", + "kind": "remoteSourceControl", + "location": "https://github.com/something/Commandant.git", + "state": { + "revision": "c281992c31c3f41c48b5036c5a38185eaec32626", + "version": "0.12.0" + } + }, + { + "identity": "scope.package", + "kind": "registry", + "location": "", + "state": { + "version": "0.12.0" + } + } + ] + } + """ ) let store = try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fs, mirrors: .init()) @@ -243,41 +247,43 @@ final class ResolvedPackagesStoreTests: XCTestCase { let originHash = UUID().uuidString - try fs.writeFileContents(packageResolvedFile, string: - """ - { - "version": 3, - "originHash": "\(originHash)", - "pins": [ - { - "identity": "clang_c", - "kind": "remoteSourceControl", - "location": "https://github.com/something/Clang_C.git", - "state": { - "revision": "90a9574276f0fd17f02f58979423c3fd4d73b59e", - "version": "1.0.2", - } - }, - { - "identity": "commandant", - "kind": "remoteSourceControl", - "location": "https://github.com/something/Commandant.git", - "state": { - "revision": "c281992c31c3f41c48b5036c5a38185eaec32626", - "version": "0.12.0" - } - }, - { - "identity": "scope.package", - "kind": "registry", - "location": "", - "state": { - "version": "0.12.0" - } - } - ] - } - """ + try fs.writeFileContents( + packageResolvedFile, + string: + """ + { + "version": 3, + "originHash": "\(originHash)", + "pins": [ + { + "identity": "clang_c", + "kind": "remoteSourceControl", + "location": "https://github.com/something/Clang_C.git", + "state": { + "revision": "90a9574276f0fd17f02f58979423c3fd4d73b59e", + "version": "1.0.2", + } + }, + { + "identity": "commandant", + "kind": "remoteSourceControl", + "location": "https://github.com/something/Commandant.git", + "state": { + "revision": "c281992c31c3f41c48b5036c5a38185eaec32626", + "version": "0.12.0" + } + }, + { + "identity": "scope.package", + "kind": "registry", + "location": "", + "state": { + "version": "0.12.0" + } + } + ] + } + """ ) let store = try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fs, mirrors: .init()) @@ -292,9 +298,13 @@ final class ResolvedPackagesStoreTests: XCTestCase { let version = -1 try fs.writeFileContents(packageResolvedFile, string: "{ \"version\": \(version) }"); - XCTAssertThrowsError(try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fs, mirrors: .init()), "error expected", { error in - XCTAssertEqual("\(error)", "\(packageResolvedFile) file is corrupted or malformed; fix or delete the file to continue: unknown 'Package.resolved' version '\(version)' at '\(packageResolvedFile)'.") - }) + XCTAssertThrowsError( + try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fs, mirrors: .init()), + "error expected", + { error in + XCTAssertEqual("\(error)", "\(packageResolvedFile) file is corrupted or malformed; fix or delete the file to continue: unknown 'Package.resolved' version '\(version)' at '\(packageResolvedFile)'.") + } + ) } @@ -304,9 +314,13 @@ final class ResolvedPackagesStoreTests: XCTestCase { try fs.writeFileContents(packageResolvedFile, string: "boom") - XCTAssertThrowsError(try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fs, mirrors: .init()), "error expected", { error in - XCTAssertMatch("\(error)", .contains("\(packageResolvedFile) file is corrupted or malformed; fix or delete the file to continue")) - }) + XCTAssertThrowsError( + try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fs, mirrors: .init()), + "error expected", + { error in + XCTAssertMatch("\(error)", .contains("\(packageResolvedFile) file is corrupted or malformed; fix or delete the file to continue")) + } + ) } func testEmptyPackageResolved() throws { @@ -355,12 +369,18 @@ final class ResolvedPackagesStoreTests: XCTestCase { let store = try ResolvedPackagesStore(packageResolvedFile: packageResolvedFile, workingDirectory: .root, fileSystem: fileSystem, mirrors: mirrors) - store.track(packageRef: .remoteSourceControl(identity: fooIdentity, url: fooMirroredURL), - state: .version(v1, revision: "foo-revision")) - store.track(packageRef: .remoteSourceControl(identity: barIdentity, url: barMirroredURL), - state: .version(v1, revision: "bar-revision")) - store.track(packageRef: .remoteSourceControl(identity: bazIdentity, url: bazURL), - state: .version(v1, revision: "baz-revision")) + store.track( + packageRef: .remoteSourceControl(identity: fooIdentity, url: fooMirroredURL), + state: .version(v1, revision: "foo-revision") + ) + store.track( + packageRef: .remoteSourceControl(identity: barIdentity, url: barMirroredURL), + state: .version(v1, revision: "bar-revision") + ) + store.track( + packageRef: .remoteSourceControl(identity: bazIdentity, url: bazURL), + state: .version(v1, revision: "baz-revision") + ) XCTAssert(store.resolvedPackages.count == 3) XCTAssertEqual(store.resolvedPackages[fooIdentity]!.packageRef.kind, .remoteSourceControl(fooMirroredURL)) @@ -447,7 +467,7 @@ final class ResolvedPackagesStoreTests: XCTestCase { URL1.absoluteString: mirroredURL.absoluteString, URL2.absoluteString: mirroredURL.absoluteString, URL3.absoluteString: mirroredURL.absoluteString, - URL4.absoluteString: mirroredURL.absoluteString + URL4.absoluteString: mirroredURL.absoluteString, ]) XCTAssertEqual(mirrors.mirror(for: URL2.absoluteString), mirroredURL.absoluteString) @@ -460,7 +480,7 @@ final class ResolvedPackagesStoreTests: XCTestCase { URL1.absoluteString: mirroredURL.absoluteString, URL2.absoluteString: mirroredURL.absoluteString, URL3.absoluteString: mirroredURL.absoluteString, - URL4.absoluteString: mirroredURL.absoluteString + URL4.absoluteString: mirroredURL.absoluteString, ]) XCTAssertEqual(mirrors.mirror(for: URL3.absoluteString), mirroredURL.absoluteString) @@ -473,7 +493,7 @@ final class ResolvedPackagesStoreTests: XCTestCase { URL1.absoluteString: mirroredURL.absoluteString, URL2.absoluteString: mirroredURL.absoluteString, URL3.absoluteString: mirroredURL.absoluteString, - URL4.absoluteString: mirroredURL.absoluteString + URL4.absoluteString: mirroredURL.absoluteString, ]) XCTAssertEqual(mirrors.mirror(for: URL2.absoluteString), mirroredURL.absoluteString) @@ -487,7 +507,7 @@ final class ResolvedPackagesStoreTests: XCTestCase { URL1.absoluteString: mirroredURL.absoluteString, URL2.absoluteString: mirroredURL.absoluteString, URL3.absoluteString: mirroredURL.absoluteString, - URL4.absoluteString: mirroredURL.absoluteString + URL4.absoluteString: mirroredURL.absoluteString, ]) XCTAssertEqual(mirrors.mirror(for: URL3.absoluteString), mirroredURL.absoluteString) @@ -501,7 +521,7 @@ final class ResolvedPackagesStoreTests: XCTestCase { URL1.absoluteString: mirroredURL.absoluteString, URL2.absoluteString: mirroredURL.absoluteString, URL3.absoluteString: mirroredURL.absoluteString, - URL4.absoluteString: mirroredURL.absoluteString + URL4.absoluteString: mirroredURL.absoluteString, ]) // reverse index is sorted by "visited", then alphabetically diff --git a/Tests/WorkspaceTests/SourceControlPackageContainerTests.swift b/Tests/WorkspaceTests/SourceControlPackageContainerTests.swift index e73fb132090..ef247bdb022 100644 --- a/Tests/WorkspaceTests/SourceControlPackageContainerTests.swift +++ b/Tests/WorkspaceTests/SourceControlPackageContainerTests.swift @@ -121,13 +121,15 @@ private class MockRepositoryManagerDelegate: RepositoryManager.Delegate { private let v1: Version = "1.0.0" private let v2: Version = "2.0.0" -private let v1Range: VersionSetSpecifier = .range("1.0.0" ..< "2.0.0") +private let v1Range: VersionSetSpecifier = .range("1.0.0"..<"2.0.0") final class SourceControlPackageContainerTests: XCTestCase { func testVprefixVersions() async throws { - try XCTSkipOnWindows(because: """ - https://github.com/swiftlang/swift-package-manager/issues/8578 - """) + try XCTSkipOnWindows( + because: """ + https://github.com/swiftlang/swift-package-manager/issues/8578 + """ + ) let fs = InMemoryFileSystem() try fs.createMockToolchain() @@ -174,9 +176,11 @@ final class SourceControlPackageContainerTests: XCTestCase { } func testVersions() async throws { - try XCTSkipOnWindows(because: """ - https://github.com/swiftlang/swift-package-manager/issues/8578 - """) + try XCTSkipOnWindows( + because: """ + https://github.com/swiftlang/swift-package-manager/issues/8578 + """ + ) let fs = InMemoryFileSystem() try fs.createMockToolchain() @@ -274,9 +278,11 @@ final class SourceControlPackageContainerTests: XCTestCase { } func testPreReleaseVersions() async throws { - try XCTSkipOnWindows(because: """ - https://github.com/swiftlang/swift-package-manager/issues/8578 - """) + try XCTSkipOnWindows( + because: """ + https://github.com/swiftlang/swift-package-manager/issues/8578 + """ + ) let fs = InMemoryFileSystem() try fs.createMockToolchain() @@ -325,9 +331,11 @@ final class SourceControlPackageContainerTests: XCTestCase { } func testSimultaneousVersions() async throws { - try XCTSkipOnWindows(because: """ - https://github.com/swiftlang/swift-package-manager/issues/8578 - """) + try XCTSkipOnWindows( + because: """ + https://github.com/swiftlang/swift-package-manager/issues/8578 + """ + ) let fs = InMemoryFileSystem() try fs.createMockToolchain() @@ -380,10 +388,10 @@ final class SourceControlPackageContainerTests: XCTestCase { } func testDependencyConstraints() throws { -#if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION -#else - try XCTSkipIf(true, "Target based dependency resolution is disabled") -#endif + #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION + #else + try XCTSkipIf(true, "Target based dependency resolution is disabled") + #endif let dependencies: [PackageDependency] = [ .localSourceControl(path: "/Bar1", requirement: .upToNextMajor(from: "1.0.0")), @@ -392,7 +400,7 @@ final class SourceControlPackageContainerTests: XCTestCase { ] let products = [ - try ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo1"]), + try ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo1"]) ] let targets = [ @@ -548,7 +556,7 @@ final class SourceControlPackageContainerTests: XCTestCase { displayName: packageDir.basename, path: packageDir, targets: [ - try TargetDescription(name: packageDir.basename, path: packageDir.pathString), + try TargetDescription(name: packageDir.basename, path: packageDir.pathString) ] ) let containerProvider = try Workspace._init( @@ -564,8 +572,7 @@ final class SourceControlPackageContainerTests: XCTestCase { let container = try await containerProvider.getContainer(for: packageRef) as! SourceControlPackageContainer // Simulate accessing a fictitious dependency on the `master` branch, and check that we get back the expected error. - do { _ = try await container.getDependencies(at: "master", productFilter: .everything) } - catch let error as SourceControlPackageContainer.GetDependenciesError { + do { _ = try await container.getDependencies(at: "master", productFilter: .everything) } catch let error as SourceControlPackageContainer.GetDependenciesError { // We expect to get an error message that mentions main. XCTAssertMatch(error.description, .and(.prefix("could not find a branch named ‘master’"), .suffix("(did you mean ‘main’?)"))) XCTAssertMatch(error.repository.description, .suffix("SomePackage")) @@ -573,8 +580,7 @@ final class SourceControlPackageContainerTests: XCTestCase { } // Simulate accessing a fictitious dependency on some random commit that doesn't exist, and check that we get back the expected error. - do { _ = try await container.getDependencies(at: "535f4cb5b4a0872fa691473e82d7b27b9894df00", productFilter: .everything) } - catch let error as SourceControlPackageContainer.GetDependenciesError { + do { _ = try await container.getDependencies(at: "535f4cb5b4a0872fa691473e82d7b27b9894df00", productFilter: .everything) } catch let error as SourceControlPackageContainer.GetDependenciesError { // We expect to get an error message about the specific commit. XCTAssertMatch(error.description, .prefix("could not find the commit 535f4cb5b4a0872fa691473e82d7b27b9894df00")) XCTAssertMatch(error.repository.description, .suffix("SomePackage")) @@ -594,7 +600,6 @@ final class SourceControlPackageContainerTests: XCTestCase { try localFileSystem.writeFileContents(packageDirectory.appending(Manifest.filename), string: "") try ToolsVersionSpecificationWriter.rewriteSpecification(manifestDirectory: packageDirectory, toolsVersion: .current, fileSystem: localFileSystem) - let repositoryProvider = GitRepositoryProvider() let repositoryManagerDelegate = MockRepositoryManagerDelegate() let repositoryManager = RepositoryManager( @@ -614,7 +619,7 @@ final class SourceControlPackageContainerTests: XCTestCase { displayName: packageDirectory.basename, path: packageDirectory, targets: [ - try TargetDescription(name: packageDirectory.basename, path: packageDirectory.pathString), + try TargetDescription(name: packageDirectory.basename, path: packageDirectory.pathString) ] ) ] @@ -713,7 +718,7 @@ final class SourceControlPackageContainerTests: XCTestCase { try TargetDescription( name: "Target", dependencies: [.product(name: "DependencyProduct", package: "Dependency")] - ), + ) ] ) let containerProvider = try Workspace._init( @@ -732,8 +737,8 @@ final class SourceControlPackageContainerTests: XCTestCase { let forNothing = try await container.getDependencies(at: version, productFilter: .specific([]), ["default"]) let forProduct = try await container.getDependencies(at: version, productFilter: .specific(["Product"]), ["default"]) #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - // If the cache overlaps (incorrectly), these will be the same. - XCTAssertNotEqual(forNothing, forProduct) + // If the cache overlaps (incorrectly), these will be the same. + XCTAssertNotEqual(forNothing, forProduct) #endif } } @@ -751,7 +756,7 @@ extension PackageContainerProvider { observabilityScope: ObservabilitySystem.NOOP, on: .global(), completion: { - continuation.resume(with: $0) + continuation.resume(with: $0) } ) } @@ -763,7 +768,7 @@ extension RepositoryManager { fileSystem: FileSystem, path: AbsolutePath, provider: RepositoryProvider, - cachePath: AbsolutePath? = .none, + cachePath: AbsolutePath? = .none, cacheLocalPackages: Bool = false, delegate: RepositoryManagerDelegate? = .none ) { diff --git a/Tests/WorkspaceTests/ToolsVersionSpecificationGenerationTests.swift b/Tests/WorkspaceTests/ToolsVersionSpecificationGenerationTests.swift index 8e84be7d014..2519c13ecb2 100644 --- a/Tests/WorkspaceTests/ToolsVersionSpecificationGenerationTests.swift +++ b/Tests/WorkspaceTests/ToolsVersionSpecificationGenerationTests.swift @@ -31,13 +31,13 @@ fileprivate struct ToolsVersionSpecificationGenerationTests { #expect(versionWithNonZeroPatch.specification(roundedTo: .minor) == "// swift-tools-version:4.3") #expect(versionWithNonZeroPatch.specification(roundedTo: .patch) == "// swift-tools-version:4.3.2") - let versionWithZeroPatch = ToolsVersion.v5_3 // 5.3.0 + let versionWithZeroPatch = ToolsVersion.v5_3 // 5.3.0 #expect(versionWithZeroPatch.specification() == "// swift-tools-version:5.3") #expect(versionWithZeroPatch.specification(roundedTo: .automatic) == "// swift-tools-version:5.3") #expect(versionWithZeroPatch.specification(roundedTo: .minor) == "// swift-tools-version:5.3") #expect(versionWithZeroPatch.specification(roundedTo: .patch) == "// swift-tools-version:5.3.0") - let newMajorVersion = ToolsVersion.v5 // 5.0.0 + let newMajorVersion = ToolsVersion.v5 // 5.0.0 #expect(newMajorVersion.specification() == "// swift-tools-version:5.0") #expect(newMajorVersion.specification(roundedTo: .automatic) == "// swift-tools-version:5.0") #expect(newMajorVersion.specification(roundedTo: .minor) == "// swift-tools-version:5.0") diff --git a/Tests/WorkspaceTests/ToolsVersionSpecificationRewriterTests.swift b/Tests/WorkspaceTests/ToolsVersionSpecificationRewriterTests.swift index 729ebcad731..7ec81059153 100644 --- a/Tests/WorkspaceTests/ToolsVersionSpecificationRewriterTests.swift +++ b/Tests/WorkspaceTests/ToolsVersionSpecificationRewriterTests.swift @@ -29,7 +29,7 @@ fileprivate struct ToolsVersionSpecificationRewriterTests { let expected: String } @Test( - arguments:[ + arguments: [ NonVersionSpecificManifestTestData( id: "Empty file.", content: "", @@ -51,45 +51,45 @@ fileprivate struct ToolsVersionSpecificationRewriterTests { NonVersionSpecificManifestTestData( id: "File already having a valid version specifier.", content: """ - // swift-tools-version:3.1.2 - ... - """, + // swift-tools-version:3.1.2 + ... + """, version: ToolsVersion(version: "4.1.2"), expected: "// swift-tools-version:4.1.2\n..." ), NonVersionSpecificManifestTestData( id: "File already having a valid version specifier.", content: """ - // swift-tools-version:3.1.2 - ... - """, + // swift-tools-version:3.1.2 + ... + """, version: ToolsVersion(version: "2.1.0"), expected: "// swift-tools-version:2.1\n..." ), NonVersionSpecificManifestTestData( id: "Contents with invalid tools version specification (ignoring the validity of the version specifier).", content: """ - // swift-tool-version:3.1.2 - ... - """, + // swift-tool-version:3.1.2 + ... + """, version: ToolsVersion(version: "4.1.2"), - expected: "// swift-tools-version:4.1.2\n// swift-tool-version:3.1.2\n..." + expected: "// swift-tools-version:4.1.2\n// swift-tool-version:3.1.2\n..." ), NonVersionSpecificManifestTestData( id: "Contents with invalid version specifier.", content: """ - // swift-tools-version:3.1.2 - ... - """, + // swift-tools-version:3.1.2 + ... + """, version: ToolsVersion(version: "4.1.2"), expected: "// swift-tools-version:4.1.2\n..." ), NonVersionSpecificManifestTestData( id: "Contents with invalid version specifier and some meta data.", content: """ - // swift-tools-version:3.1.2 - ... - """, + // swift-tools-version:3.1.2 + ... + """, version: ToolsVersion(version: "4.1.2"), expected: "// swift-tools-version:4.1.2\n..." ), @@ -98,13 +98,13 @@ fileprivate struct ToolsVersionSpecificationRewriterTests { content: "let package = ... \n", version: ToolsVersion(version: "4.1.2-alpha.beta+sha.1234"), expected: "// swift-tools-version:4.1.2\nlet package = ... \n" - ) + ), ] ) func nonVersionSpecificManifests(_ data: NonVersionSpecificManifestTestData) throws { let content = data.content let version = data.version - let expected = data.expected + let expected = data.expected let inMemoryFileSystem = InMemoryFileSystem() @@ -130,13 +130,13 @@ fileprivate struct ToolsVersionSpecificationRewriterTests { let inMemoryFileSystem = InMemoryFileSystem() let manifestFilePath = AbsolutePath("/pkg/Package.swift/Package.swift") - try inMemoryFileSystem.createDirectory(manifestFilePath.parentDirectory, recursive: true) // /pkg/Package.swift/ + try inMemoryFileSystem.createDirectory(manifestFilePath.parentDirectory, recursive: true) // /pkg/Package.swift/ // Test `ManifestAccessError.Kind.isADirectory` - #expect{ + #expect { try ToolsVersionSpecificationWriter.rewriteSpecification( - manifestDirectory: manifestFilePath.parentDirectory.parentDirectory, // /pkg/ + manifestDirectory: manifestFilePath.parentDirectory.parentDirectory, // /pkg/ toolsVersion: toolsVersion, fileSystem: inMemoryFileSystem ) @@ -154,7 +154,7 @@ fileprivate struct ToolsVersionSpecificationRewriterTests { // Test `ManifestAccessError.Kind.noSuchFileOrDirectory` #expect { try ToolsVersionSpecificationWriter.rewriteSpecification( - manifestDirectory: manifestFilePath.parentDirectory, // /pkg/Package.swift/ + manifestDirectory: manifestFilePath.parentDirectory, // /pkg/Package.swift/ toolsVersion: toolsVersion, fileSystem: inMemoryFileSystem ) diff --git a/Tests/WorkspaceTests/WorkspaceStateTests.swift b/Tests/WorkspaceTests/WorkspaceStateTests.swift index aba7f6d701a..05ee0d85963 100644 --- a/Tests/WorkspaceTests/WorkspaceStateTests.swift +++ b/Tests/WorkspaceTests/WorkspaceStateTests.swift @@ -27,63 +27,63 @@ fileprivate struct WorkspaceStateTests { try fs.writeFileContents( statePath, string: """ - { - "version": 4, - "object": { - "artifacts": [], - "dependencies": [ - { - "basedOn": null, - "packageRef": { - "identity": "yams", - "kind": "remote", - "location": "https://github.com/jpsim/Yams.git", - "name": "Yams" - }, - "state": { - "checkoutState": { - "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", - "version": "4.0.6" - }, - "name": "checkout" - }, - "subpath": "Yams" - }, - { - "basedOn": null, - "packageRef": { - "identity": "swift-tools-support-core", - "kind": "remote", - "location": "https://github.com/apple/swift-tools-support-core.git", - "name": "swift-tools-support-core" - }, - "state": { - "checkoutState": { - "branch": "main", - "revision": "f9bbd6b80d67408021576adf6247e17c2e957d92", - "version": null - }, - "name": "checkout" - }, - "subpath": "swift-tools-support-core" - }, - { - "basedOn": null, - "packageRef": { - "identity": "swift-argument-parser", - "kind": "local", - "location": "/Users/tomerd/code/swift/swift-argument-parser", - "name": "swift-argument-parser" - }, - "state": { - "name": "local" - }, - "subpath": "swift-argument-parser" - } - ] + { + "version": 4, + "object": { + "artifacts": [], + "dependencies": [ + { + "basedOn": null, + "packageRef": { + "identity": "yams", + "kind": "remote", + "location": "https://github.com/jpsim/Yams.git", + "name": "Yams" + }, + "state": { + "checkoutState": { + "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", + "version": "4.0.6" + }, + "name": "checkout" + }, + "subpath": "Yams" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-tools-support-core", + "kind": "remote", + "location": "https://github.com/apple/swift-tools-support-core.git", + "name": "swift-tools-support-core" + }, + "state": { + "checkoutState": { + "branch": "main", + "revision": "f9bbd6b80d67408021576adf6247e17c2e957d92", + "version": null + }, + "name": "checkout" + }, + "subpath": "swift-tools-support-core" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-argument-parser", + "kind": "local", + "location": "/Users/tomerd/code/swift/swift-argument-parser", + "name": "swift-argument-parser" + }, + "state": { + "name": "local" + }, + "subpath": "swift-argument-parser" + } + ] + } } - } - """ + """ ) let dependencies = await WorkspaceState(fileSystem: fs, storageDirectory: buildDir).dependencies @@ -105,63 +105,63 @@ fileprivate struct WorkspaceStateTests { try fs.writeFileContents( statePath, string: """ - { - "version": 4, - "object": { - "artifacts": [], - "dependencies": [ - { - "basedOn": null, - "packageRef": { - "identity": "yams", - "kind": "remote", - "path": "https://github.com/jpsim/Yams.git", - "name": "Yams" - }, - "state": { - "checkoutState": { - "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", - "version": "4.0.6" - }, - "name": "checkout" - }, - "subpath": "Yams" - }, - { - "basedOn": null, - "packageRef": { - "identity": "swift-tools-support-core", - "kind": "remote", - "path": "https://github.com/apple/swift-tools-support-core.git", - "name": "swift-tools-support-core" - }, - "state": { - "checkoutState": { - "branch": "main", - "revision": "f9bbd6b80d67408021576adf6247e17c2e957d92", - "version": null - }, - "name": "checkout" - }, - "subpath": "swift-tools-support-core" - }, - { - "basedOn": null, - "packageRef": { - "identity": "swift-argument-parser", - "kind": "local", - "path": "/Users/tomerd/code/swift/swift-argument-parser", - "name": "swift-argument-parser" - }, - "state": { - "name": "local" - }, - "subpath": "swift-argument-parser" - } - ] + { + "version": 4, + "object": { + "artifacts": [], + "dependencies": [ + { + "basedOn": null, + "packageRef": { + "identity": "yams", + "kind": "remote", + "path": "https://github.com/jpsim/Yams.git", + "name": "Yams" + }, + "state": { + "checkoutState": { + "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", + "version": "4.0.6" + }, + "name": "checkout" + }, + "subpath": "Yams" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-tools-support-core", + "kind": "remote", + "path": "https://github.com/apple/swift-tools-support-core.git", + "name": "swift-tools-support-core" + }, + "state": { + "checkoutState": { + "branch": "main", + "revision": "f9bbd6b80d67408021576adf6247e17c2e957d92", + "version": null + }, + "name": "checkout" + }, + "subpath": "swift-tools-support-core" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-argument-parser", + "kind": "local", + "path": "/Users/tomerd/code/swift/swift-argument-parser", + "name": "swift-argument-parser" + }, + "state": { + "name": "local" + }, + "subpath": "swift-argument-parser" + } + ] + } } - } - """ + """ ) let dependencies = await WorkspaceState(fileSystem: fs, storageDirectory: buildDir).dependencies @@ -183,63 +183,63 @@ fileprivate struct WorkspaceStateTests { try fs.writeFileContents( statePath, string: """ - { - "version": 5, - "object": { - "artifacts": [], - "dependencies": [ - { - "basedOn": null, - "packageRef": { - "identity": "yams", - "kind": "remoteSourceControl", - "location": "https://github.com/jpsim/Yams.git", - "name": "Yams" - }, - "state": { - "checkoutState": { - "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", - "version": "4.0.6" - }, - "name": "checkout" - }, - "subpath": "Yams" - }, - { - "basedOn": null, - "packageRef": { - "identity": "swift-tools-support-core", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-tools-support-core.git", - "name": "swift-tools-support-core" - }, - "state": { - "checkoutState": { - "branch": "main", - "revision": "f9bbd6b80d67408021576adf6247e17c2e957d92" - }, - "name": "checkout" - }, - "subpath": "swift-tools-support-core" - }, - { - "basedOn": null, - "packageRef": { - "identity": "swift-argument-parser", - "kind": "fileSystem", - "location": "/Users/tomerd/code/swift/swift-argument-parser", - "name": "swift-argument-parser" - }, - "state": { - "name": "local", - "path": "/Users/tomerd/code/swift/swift-argument-parser" - }, - "subpath": "swift-argument-parser" - } - ] + { + "version": 5, + "object": { + "artifacts": [], + "dependencies": [ + { + "basedOn": null, + "packageRef": { + "identity": "yams", + "kind": "remoteSourceControl", + "location": "https://github.com/jpsim/Yams.git", + "name": "Yams" + }, + "state": { + "checkoutState": { + "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", + "version": "4.0.6" + }, + "name": "checkout" + }, + "subpath": "Yams" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-tools-support-core", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-tools-support-core.git", + "name": "swift-tools-support-core" + }, + "state": { + "checkoutState": { + "branch": "main", + "revision": "f9bbd6b80d67408021576adf6247e17c2e957d92" + }, + "name": "checkout" + }, + "subpath": "swift-tools-support-core" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-argument-parser", + "kind": "fileSystem", + "location": "/Users/tomerd/code/swift/swift-argument-parser", + "name": "swift-argument-parser" + }, + "state": { + "name": "local", + "path": "/Users/tomerd/code/swift/swift-argument-parser" + }, + "subpath": "swift-argument-parser" + } + ] + } } - } - """ + """ ) let dependencies = await WorkspaceState(fileSystem: fs, storageDirectory: buildDir).dependencies @@ -261,49 +261,49 @@ fileprivate struct WorkspaceStateTests { try fs.writeFileContents( statePath, string: """ - { - "version": 5, - "object": { - "artifacts": [], - "dependencies": [ - { - "basedOn": null, - "packageRef": { - "identity": "yams", - "kind": "remoteSourceControl", - "location": "https://github.com/jpsim/Yams.git", - "name": "Yams" - }, - "state": { - "checkoutState": { - "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", - "version": "4.0.6" - }, - "name": "checkout" - }, - "subpath": "Yams" - }, - { - "basedOn": null, - "packageRef": { - "identity": "swift-argument-parser", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-argument-parser.git", - "name": "swift-argument-parser" - }, - "state": { - "checkoutState": { - "revision": "83b23d940471b313427da226196661856f6ba3e0", - "version": "0.4.4" - }, - "name": "checkout" - }, - "subpath": "swift-argument-parser" - } - ] + { + "version": 5, + "object": { + "artifacts": [], + "dependencies": [ + { + "basedOn": null, + "packageRef": { + "identity": "yams", + "kind": "remoteSourceControl", + "location": "https://github.com/jpsim/Yams.git", + "name": "Yams" + }, + "state": { + "checkoutState": { + "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", + "version": "4.0.6" + }, + "name": "checkout" + }, + "subpath": "Yams" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-argument-parser", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-argument-parser.git", + "name": "swift-argument-parser" + }, + "state": { + "checkoutState": { + "revision": "83b23d940471b313427da226196661856f6ba3e0", + "version": "0.4.4" + }, + "name": "checkout" + }, + "subpath": "swift-argument-parser" + } + ] + } } - } - """ + """ ) let state = WorkspaceState(fileSystem: fs, storageDirectory: buildDir) @@ -330,60 +330,60 @@ fileprivate struct WorkspaceStateTests { try fs.writeFileContents( statePath, string: """ - { - "version": 5, - "object": { - "artifacts": [ - { - "packageRef": { - "identity": "foo", - "kind": "remoteSourceControl", - "location": "https://github.com/org/foo.git", - "name": "foo" - }, - "targetName": "foo", - "source": { - "type": "remote", - "url": "https://github.com/org/binary1.zip", - "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" - }, - "path": "/path/to/binary1" - }, - { - "packageRef": { - "identity": "foo", - "kind": "remoteSourceControl", - "location": "https://github.com/org/foo.git", - "name": "foo" - }, - "targetName": "bar", - "source": { - "type": "remote", - "url": "https://github.com/org/binary2.zip", - "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" - }, - "path": "/path/to/binary2" - }, - { - "packageRef": { - "identity": "bar", - "kind": "remoteSourceControl", - "location": "https://github.com/org/bar.git", - "name": "bar" - }, - "targetName": "bar", - "source": { - "type": "remote", - "url": "https://github.com/org/binary3.zip", - "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" - }, - "path": "/path/to/binary3" - } - ], - "dependencies": [] + { + "version": 5, + "object": { + "artifacts": [ + { + "packageRef": { + "identity": "foo", + "kind": "remoteSourceControl", + "location": "https://github.com/org/foo.git", + "name": "foo" + }, + "targetName": "foo", + "source": { + "type": "remote", + "url": "https://github.com/org/binary1.zip", + "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" + }, + "path": "/path/to/binary1" + }, + { + "packageRef": { + "identity": "foo", + "kind": "remoteSourceControl", + "location": "https://github.com/org/foo.git", + "name": "foo" + }, + "targetName": "bar", + "source": { + "type": "remote", + "url": "https://github.com/org/binary2.zip", + "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" + }, + "path": "/path/to/binary2" + }, + { + "packageRef": { + "identity": "bar", + "kind": "remoteSourceControl", + "location": "https://github.com/org/bar.git", + "name": "bar" + }, + "targetName": "bar", + "source": { + "type": "remote", + "url": "https://github.com/org/binary3.zip", + "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" + }, + "path": "/path/to/binary3" + } + ], + "dependencies": [] + } } - } - """ + """ ) let artifacts = await WorkspaceState(fileSystem: fs, storageDirectory: buildDir).artifacts @@ -406,49 +406,49 @@ fileprivate struct WorkspaceStateTests { try fs.writeFileContents( statePath, string: """ - { - "version": 5, - "object": { - "artifacts": [], - "dependencies": [ - { - "basedOn": null, - "packageRef": { - "identity": "yams", - "kind": "remoteSourceControl", - "location": "https://github.com/jpsim/Yams.git", - "name": "Yams" - }, - "state": { - "checkoutState": { - "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", - "version": "4.0.6" - }, - "name": "checkout" - }, - "subpath": "Yams" - }, - { - "basedOn": null, - "packageRef": { - "identity": "yams", - "kind": "remoteSourceControl", - "location": "https://github.com/jpsim/Yams.git", - "name": "Yams" - }, - "state": { - "checkoutState": { - "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", - "version": "4.0.6" - }, - "name": "checkout" - }, - "subpath": "Yams" - }, - ] + { + "version": 5, + "object": { + "artifacts": [], + "dependencies": [ + { + "basedOn": null, + "packageRef": { + "identity": "yams", + "kind": "remoteSourceControl", + "location": "https://github.com/jpsim/Yams.git", + "name": "Yams" + }, + "state": { + "checkoutState": { + "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", + "version": "4.0.6" + }, + "name": "checkout" + }, + "subpath": "Yams" + }, + { + "basedOn": null, + "packageRef": { + "identity": "yams", + "kind": "remoteSourceControl", + "location": "https://github.com/jpsim/Yams.git", + "name": "Yams" + }, + "state": { + "checkoutState": { + "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", + "version": "4.0.6" + }, + "name": "checkout" + }, + "subpath": "Yams" + }, + ] + } } - } - """ + """ ) let dependencies = await WorkspaceState(fileSystem: fs, storageDirectory: buildDir).dependencies @@ -471,45 +471,45 @@ fileprivate struct WorkspaceStateTests { try fs.writeFileContents( statePath, string: """ - { - "version": 5, - "object": { - "artifacts": [ - { - "packageRef": { - "identity": "foo", - "kind": "remoteSourceControl", - "location": "https://github.com/org/foo.git", - "name": "foo" - }, - "targetName": "foo", - "source": { - "type": "remote", - "url": "https://github.com/org/binary1.zip", - "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" - }, - "path": "/path/to/binary1" - }, - { - "packageRef": { - "identity": "foo", - "kind": "remoteSourceControl", - "location": "https://github.com/org/foo.git", - "name": "foo" - }, - "targetName": "foo", - "source": { - "type": "remote", - "url": "https://github.com/org/binary2.zip", - "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" - }, - "path": "/path/to/binary2" - } - ], - "dependencies": [] + { + "version": 5, + "object": { + "artifacts": [ + { + "packageRef": { + "identity": "foo", + "kind": "remoteSourceControl", + "location": "https://github.com/org/foo.git", + "name": "foo" + }, + "targetName": "foo", + "source": { + "type": "remote", + "url": "https://github.com/org/binary1.zip", + "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" + }, + "path": "/path/to/binary1" + }, + { + "packageRef": { + "identity": "foo", + "kind": "remoteSourceControl", + "location": "https://github.com/org/foo.git", + "name": "foo" + }, + "targetName": "foo", + "source": { + "type": "remote", + "url": "https://github.com/org/binary2.zip", + "checksum": "77AFD0BA-D1CF-4628-A43B-B6E66F44448A" + }, + "path": "/path/to/binary2" + } + ], + "dependencies": [] + } } - } - """ + """ ) let artifacts = await WorkspaceState(fileSystem: fs, storageDirectory: buildDir).artifacts diff --git a/Tests/WorkspaceTests/WorkspaceTests+Traits.swift b/Tests/WorkspaceTests/WorkspaceTests+Traits.swift index 4cad90c1de3..5527bfbdec6 100644 --- a/Tests/WorkspaceTests/WorkspaceTests+Traits.swift +++ b/Tests/WorkspaceTests/WorkspaceTests+Traits.swift @@ -47,33 +47,33 @@ extension WorkspaceTests { MockTarget(name: "Bar", dependencies: ["Baz"]), ], products: [ - MockProduct(name: "Foo", modules: ["Foo", "Bar"]), + MockProduct(name: "Foo", modules: ["Foo", "Bar"]) ], dependencies: [ .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Boo", requirement: .upToNextMajor(from: "1.0.0")), ], traits: ["Trait1", "Trait2"] - ), + ) ], packages: [ MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.5.0"] ), MockPackage( name: "Boo", targets: [ - MockTarget(name: "Boo"), + MockTarget(name: "Boo") ], products: [ - MockProduct(name: "Boo", modules: ["Boo"]), + MockProduct(name: "Boo", modules: ["Boo"]) ], versions: ["1.0.0", "1.5.0"] ), @@ -84,7 +84,7 @@ extension WorkspaceTests { ) let deps: [MockDependency] = [ - .sourceControl(path: "./Baz", requirement: .exact("1.0.0"), products: .specific(["Baz"])), + .sourceControl(path: "./Baz", requirement: .exact("1.0.0"), products: .specific(["Baz"])) ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in @@ -131,33 +131,33 @@ extension WorkspaceTests { MockTarget(name: "Bar", dependencies: ["Baz"]), ], products: [ - MockProduct(name: "Foo", modules: ["Foo", "Bar"]), + MockProduct(name: "Foo", modules: ["Foo", "Bar"]) ], dependencies: [ .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Boo", requirement: .upToNextMajor(from: "1.0.0")), ], traits: [.init(name: "default", enabledTraits: ["Trait2"]), "Trait1", "Trait2"] - ), + ) ], packages: [ MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.5.0"] ), MockPackage( name: "Boo", targets: [ - MockTarget(name: "Boo"), + MockTarget(name: "Boo") ], products: [ - MockProduct(name: "Boo", modules: ["Boo"]), + MockProduct(name: "Boo", modules: ["Boo"]) ], versions: ["1.0.0", "1.5.0"] ), @@ -219,7 +219,7 @@ extension WorkspaceTests { MockTarget(name: "Bar", dependencies: ["Baz"]), ], products: [ - MockProduct(name: "Foo", modules: ["Foo", "Bar"]), + MockProduct(name: "Foo", modules: ["Foo", "Bar"]) ], dependencies: [ .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), @@ -229,19 +229,19 @@ extension WorkspaceTests { .sourceControl(path: "./Bam", requirement: .upToNextMajor(from: "1.0.0")), ], traits: [.init(name: "default", enabledTraits: ["Trait2"]), "Trait1", "Trait2"] - ), + ) ], packages: [ MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.5.0"] - ), + ) ], // Trait configuration overrides default traits; no traits enabled traitConfiguration: .init(enabledTraits: [], enableAllTraits: false), @@ -285,7 +285,7 @@ extension WorkspaceTests { .product( name: "Baz", package: "Baz", - condition: .init(traits: ["Trait1"]) // Baz dependency guarded by traits. + condition: .init(traits: ["Trait1"]) // Baz dependency guarded by traits. ), .product( name: "Boo", @@ -294,36 +294,36 @@ extension WorkspaceTests { ), ] ), - MockTarget(name: "Bar", dependencies: ["Baz"]), // Baz dependency not guarded by traits. + MockTarget(name: "Bar", dependencies: ["Baz"]), // Baz dependency not guarded by traits. ], products: [ - MockProduct(name: "Foo", modules: ["Foo", "Bar"]), + MockProduct(name: "Foo", modules: ["Foo", "Bar"]) ], dependencies: [ .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Boo", requirement: .upToNextMajor(from: "1.0.0")), ], traits: [.init(name: "default", enabledTraits: ["Trait2"]), "Trait1", "Trait2"] - ), + ) ], packages: [ MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.5.0"] ), MockPackage( name: "Boo", targets: [ - MockTarget(name: "Boo"), + MockTarget(name: "Boo") ], products: [ - MockProduct(name: "Boo", modules: ["Boo"]), + MockProduct(name: "Boo", modules: ["Boo"]) ], versions: ["1.0.0", "1.5.0"] ), @@ -367,37 +367,37 @@ extension WorkspaceTests { name: "Baz", package: "Baz", condition: .init(traits: ["Trait1"]) - ), + ) ] ), MockTarget(name: "Bar", dependencies: ["Baz"]), ], products: [ - MockProduct(name: "Foo", modules: ["Foo", "Bar"]), + MockProduct(name: "Foo", modules: ["Foo", "Bar"]) ], dependencies: [ - .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0"), traits: ["TraitNotFound"]), + .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0"), traits: ["TraitNotFound"]) ], traits: [.init(name: "default", enabledTraits: ["Trait2"]), "Trait1", "Trait2"] - ), + ) ], packages: [ MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], traits: ["TraitFound"], versions: ["1.0.0", "1.5.0"] - ), + ) ] ) let deps: [MockDependency] = [ - .sourceControl(path: "./Baz", requirement: .exact("1.0.0"), products: .specific(["Baz"]), traits: ["TraitFound"]), + .sourceControl(path: "./Baz", requirement: .exact("1.0.0"), products: .specific(["Baz"]), traits: ["TraitFound"]) ] try await workspace.checkPackageGraphFailure(roots: ["Foo"], deps: deps) { diagnostics in @@ -428,39 +428,39 @@ extension WorkspaceTests { name: "Baz", package: "Baz", condition: .init(traits: ["Trait1"]) - ), + ) ] ), MockTarget(name: "Bar", dependencies: ["Baz"]), ], products: [ - MockProduct(name: "Foo", modules: ["Foo", "Bar"]), + MockProduct(name: "Foo", modules: ["Foo", "Bar"]) ], dependencies: [ - .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0"), traits: ["TraitFound"]), + .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0"), traits: ["TraitFound"]) ], traits: [.init(name: "default", enabledTraits: ["Trait2"]), "Trait1", "Trait2"] - ), + ) ], packages: [ MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], traits: ["TraitFound"], versions: ["1.0.0", "1.5.0"] - ), + ) ], // Trait configuration containing trait that isn't defined in the root package. traitConfiguration: .enabledTraits(["TraitNotFound"]), ) let deps: [MockDependency] = [ - .sourceControl(path: "./Baz", requirement: .exact("1.0.0"), products: .specific(["Baz"]), traits: ["TraitFound"]), + .sourceControl(path: "./Baz", requirement: .exact("1.0.0"), products: .specific(["Baz"]), traits: ["TraitFound"]) ] try await workspace.checkPackageGraphFailure(roots: ["Foo"], deps: deps) { diagnostics in @@ -489,38 +489,37 @@ extension WorkspaceTests { name: "Icing", package: "Sugar", condition: .init(traits: ["BreakfastOfChampions", "DontTellMom"]) - ), + ) ] - ), + ) ], products: [ MockProduct(name: "YummyBreakfast", modules: ["Wheat"]) ], dependencies: [ - .sourceControl(path: "./Sugar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Sugar", requirement: .upToNextMajor(from: "1.0.0")) ], traits: ["BreakfastOfChampions", "DontTellMom"] - ), + ) ], packages: [ MockPackage( name: "Sugar", targets: [ - MockTarget(name: "Icing"), + MockTarget(name: "Icing") ], products: [ - MockProduct(name: "Icing", modules: ["Icing"]), + MockProduct(name: "Icing", modules: ["Icing"]) ], versions: ["1.0.0", "1.5.0"] - ), + ) ], traitConfiguration: traitConfiguration ) } - let deps: [MockDependency] = [ - .sourceControl(path: "./Sugar", requirement: .exact("1.0.0"), products: .specific(["Icing"])), + .sourceControl(path: "./Sugar", requirement: .exact("1.0.0"), products: .specific(["Icing"])) ] let workspaceOfChampions = try await createMockWorkspace(.enabledTraits(["BreakfastOfChampions"])) @@ -604,9 +603,9 @@ extension WorkspaceTests { name: "Raisin", package: "Fruit", condition: .init(traits: ["Healthy"]) - ) + ), ] - ), + ) ], products: [ MockProduct(name: "YummyBreakfast", modules: ["Wheat"]) @@ -616,26 +615,26 @@ extension WorkspaceTests { .sourceControl(path: "./Fruit", requirement: .upToNextMajor(from: "1.0.0")), ], traits: ["Healthy", "BreakfastOfChampions"] - ), + ) ], packages: [ MockPackage( name: "Sugar", targets: [ - MockTarget(name: "Icing"), + MockTarget(name: "Icing") ], products: [ - MockProduct(name: "Icing", modules: ["Icing"]), + MockProduct(name: "Icing", modules: ["Icing"]) ], versions: ["1.0.0", "1.5.0"] ), MockPackage( name: "Fruit", targets: [ - MockTarget(name: "Raisin"), + MockTarget(name: "Raisin") ], products: [ - MockProduct(name: "Raisin", modules: ["Raisin"]), + MockProduct(name: "Raisin", modules: ["Raisin"]) ], versions: ["1.0.0", "1.2.0"] ), @@ -644,7 +643,6 @@ extension WorkspaceTests { ) } - let deps: [MockDependency] = [ .sourceControl(path: "./Sugar", requirement: .exact("1.0.0"), products: .specific(["Icing"])), .sourceControl(path: "./Fruit", requirement: .exact("1.0.0"), products: .specific(["Raisin"])), @@ -724,17 +722,17 @@ extension WorkspaceTests { .product( name: "MyProduct", package: "PackageWithDefaultTraits", - ), + ) ] - ), + ) ], products: [ MockProduct(name: "RootProduct", modules: ["MyTarget"]) ], dependencies: [ - .sourceControl(path: "./PackageWithDefaultTraits", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./PackageWithDefaultTraits", requirement: .upToNextMajor(from: "1.0.0")) ], - ), + ) ], packages: [ MockPackage( @@ -749,10 +747,10 @@ extension WorkspaceTests { condition: .init(traits: ["Enabled1"]) ) ] - ), + ) ], products: [ - MockProduct(name: "MyProduct", modules: ["PackageTarget"]), + MockProduct(name: "MyProduct", modules: ["PackageTarget"]) ], dependencies: [ .sourceControl(path: "./GuardedDependency", requirement: .upToNextMajor(from: "1.0.0")) @@ -761,7 +759,7 @@ extension WorkspaceTests { "Enabled1", "Enabled2", TraitDescription(name: "default", enabledTraits: ["Enabled1", "Enabled2"]), - "NotEnabled" + "NotEnabled", ], versions: ["1.0.0", "1.5.0"] ), @@ -776,12 +774,12 @@ extension WorkspaceTests { MockProduct(name: "GuardedProduct", modules: ["GuardedTarget"]) ], versions: ["1.0.0", "1.5.0"] - ) + ), ], ) let deps: [MockDependency] = [ - .sourceControl(path: "./PackageWithDefaultTraits", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./PackageWithDefaultTraits", requirement: .upToNextMajor(from: "1.0.0")) ] try await workspace.checkPackageGraph(roots: ["RootPackage"], deps: deps) { graph, diagnostics in @@ -822,7 +820,7 @@ extension WorkspaceTests { .product(name: "Parent1Product", package: "Parent1"), .product(name: "Parent2Product", package: "Parent2"), ] - ), + ) ], products: [ MockProduct(name: "RootProduct", modules: ["RootTarget"]) @@ -831,7 +829,7 @@ extension WorkspaceTests { .sourceControl(path: "./Parent1", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Parent2", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -842,7 +840,7 @@ extension WorkspaceTests { dependencies: [ .product(name: "ChildProduct", package: "ChildPackage") ] - ), + ) ], products: [ MockProduct(name: "Parent1Product", modules: ["Parent1Target"]) @@ -861,7 +859,7 @@ extension WorkspaceTests { dependencies: [ .product(name: "ChildProduct", package: "ChildPackage") ] - ), + ) ], products: [ MockProduct(name: "Parent2Product", modules: ["Parent2Target"]) @@ -884,7 +882,7 @@ extension WorkspaceTests { condition: .init(traits: ["Feature1"]) ) ] - ), + ) ], products: [ MockProduct(name: "ChildProduct", modules: ["ChildTarget"]) @@ -895,7 +893,7 @@ extension WorkspaceTests { traits: [ "Feature1", "Feature2", - TraitDescription(name: "default", enabledTraits: ["Feature1"]) + TraitDescription(name: "default", enabledTraits: ["Feature1"]), ], versions: ["1.0.0"] ), @@ -908,7 +906,7 @@ extension WorkspaceTests { MockProduct(name: "GuardedProduct", modules: ["GuardedTarget"]) ], versions: ["1.0.0"] - ) + ), ] ) @@ -961,20 +959,20 @@ extension WorkspaceTests { MockTarget( name: "RootTarget", dependencies: [.product(name: "ChildProduct", package: "ChildPackage")] - ), + ) ], products: [MockProduct(name: "RootProduct", modules: ["RootTarget"])], dependencies: [ // Root doesn't specify traits - wants defaults .sourceControl(path: "./ChildPackage", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "ChildPackage", targets: [ - MockTarget(name: "ChildTarget"), + MockTarget(name: "ChildTarget") ], products: [MockProduct(name: "ChildProduct", modules: ["ChildTarget"])], traits: [ @@ -983,7 +981,7 @@ extension WorkspaceTests { .init(name: "Feature1"), ], versions: ["1.0.0"] - ), + ) ] ) @@ -1036,14 +1034,14 @@ extension WorkspaceTests { .product(name: "Parent1Product", package: "Parent1"), .product(name: "Parent2Product", package: "Parent2"), ] - ), + ) ], products: [MockProduct(name: "RootProduct", modules: ["RootTarget"])], dependencies: [ .sourceControl(path: "./Parent1", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Parent2", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -1052,7 +1050,7 @@ extension WorkspaceTests { MockTarget( name: "Parent1Target", dependencies: [.product(name: "ChildProduct", package: "ChildPackage")] - ), + ) ], products: [MockProduct(name: "Parent1Product", modules: ["Parent1Target"])], dependencies: [ @@ -1067,7 +1065,7 @@ extension WorkspaceTests { MockTarget( name: "Parent2Target", dependencies: [.product(name: "ChildProduct", package: "ChildPackage")] - ), + ) ], products: [MockProduct(name: "Parent2Product", modules: ["Parent2Target"])], dependencies: [ @@ -1131,14 +1129,14 @@ extension WorkspaceTests { .product(name: "Parent1Product", package: "Parent1"), .product(name: "Parent2Product", package: "Parent2"), ] - ), + ) ], products: [MockProduct(name: "RootProduct", modules: ["RootTarget"])], dependencies: [ .sourceControl(path: "./Parent1", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Parent2", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -1147,7 +1145,7 @@ extension WorkspaceTests { MockTarget( name: "Parent1Target", dependencies: [.product(name: "ChildProduct", package: "ChildPackage")] - ), + ) ], products: [MockProduct(name: "Parent1Product", modules: ["Parent1Target"])], dependencies: [ @@ -1162,7 +1160,7 @@ extension WorkspaceTests { MockTarget( name: "Parent2Target", dependencies: [.product(name: "ChildProduct", package: "ChildPackage")] - ), + ) ], products: [MockProduct(name: "Parent2Product", modules: ["Parent2Target"])], dependencies: [ @@ -1206,4 +1204,3 @@ extension WorkspaceTests { } } - diff --git a/Tests/WorkspaceTests/WorkspaceTests.swift b/Tests/WorkspaceTests/WorkspaceTests.swift index ea2974d13c0..0c3fb35453b 100644 --- a/Tests/WorkspaceTests/WorkspaceTests.swift +++ b/Tests/WorkspaceTests/WorkspaceTests.swift @@ -58,31 +58,31 @@ final class WorkspaceTests: XCTestCase { MockTarget(name: "BarTests", dependencies: ["Bar"], type: .test), ], products: [ - MockProduct(name: "Foo", modules: ["Foo", "Bar"]), + MockProduct(name: "Foo", modules: ["Foo", "Bar"]) ], dependencies: [ - .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.5.0"] ), MockPackage( name: "Quix", targets: [ - MockTarget(name: "Quix"), + MockTarget(name: "Quix") ], products: [ - MockProduct(name: "Quix", modules: ["Quix"]), + MockProduct(name: "Quix", modules: ["Quix"]) ], versions: ["1.0.0", "1.2.0"] ), @@ -123,25 +123,25 @@ final class WorkspaceTests: XCTestCase { XCTAssertMatch( workspace.delegate.events, [ - "will load manifest for localSourceControl package: \(sandbox.appending(components: "pkgs", "Quix")) (identity: quix)", + "will load manifest for localSourceControl package: \(sandbox.appending(components: "pkgs", "Quix")) (identity: quix)" ] ) XCTAssertMatch( workspace.delegate.events, [ - "did load manifest for localSourceControl package: \(sandbox.appending(components: "pkgs", "Quix")) (identity: quix)", + "did load manifest for localSourceControl package: \(sandbox.appending(components: "pkgs", "Quix")) (identity: quix)" ] ) XCTAssertMatch( workspace.delegate.events, [ - "will load manifest for localSourceControl package: \(sandbox.appending(components: "pkgs", "Baz")) (identity: baz)", + "will load manifest for localSourceControl package: \(sandbox.appending(components: "pkgs", "Baz")) (identity: baz)" ] ) XCTAssertMatch( workspace.delegate.events, [ - "did load manifest for localSourceControl package: \(sandbox.appending(components: "pkgs", "Baz")) (identity: baz)", + "did load manifest for localSourceControl package: \(sandbox.appending(components: "pkgs", "Baz")) (identity: baz)" ] ) @@ -238,13 +238,13 @@ final class WorkspaceTests: XCTestCase { do { let ws = try createWorkspace( - """ - // swift-tools-version:6.0 - import PackageDescription - let package = Package( - name: "foo" - ) - """ + """ + // swift-tools-version:6.0 + import PackageDescription + let package = Package( + name: "foo" + ) + """ ) XCTAssertMatch(try ws.interpreterFlags(for: packageManifest), [.equal("-swift-version"), .equal("6")]) @@ -252,13 +252,13 @@ final class WorkspaceTests: XCTestCase { do { let ws = try createWorkspace( - """ - // swift-tools-version:6.1 - import PackageDescription - let package = Package( - name: "foo" - ) - """ + """ + // swift-tools-version:6.1 + import PackageDescription + let package = Package( + name: "foo" + ) + """ ) XCTAssertMatch(try ws.interpreterFlags(for: packageManifest), [.equal("-swift-version"), .equal("6")]) @@ -267,13 +267,13 @@ final class WorkspaceTests: XCTestCase { do { let ws = try createWorkspace( - """ - // swift-tools-version:6.2 - import PackageDescription - let package = Package( - name: "foo" - ) - """ + """ + // swift-tools-version:6.2 + import PackageDescription + let package = Package( + name: "foo" + ) + """ ) XCTAssertMatch(try ws.interpreterFlags(for: packageManifest), [.equal("-swift-version"), .equal("6")]) @@ -350,13 +350,13 @@ final class WorkspaceTests: XCTestCase { try localFileSystem.writeFileContents( pkgDir.appending("Package.swift"), string: """ - // swift-tools-version:4.0 - import PackageDescription - #error("An error in MyPkg") - let package = Package( - name: "MyPkg" - ) - """ + // swift-tools-version:4.0 + import PackageDescription + #error("An error in MyPkg") + let package = Package( + name: "MyPkg" + ) + """ ) let workspace = try Workspace( fileSystem: localFileSystem, @@ -396,21 +396,21 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Baz"]), + MockTarget(name: "Foo", dependencies: ["Baz"]) ], products: [], dependencies: [ - .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")) ] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar", dependencies: ["Baz"]), + MockTarget(name: "Bar", dependencies: ["Baz"]) ], products: [], dependencies: [ - .sourceControl(path: "./Baz", requirement: .exact("1.0.1")), + .sourceControl(path: "./Baz", requirement: .exact("1.0.1")) ] ), ], @@ -418,13 +418,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.0.1", "1.0.3", "1.0.5", "1.0.8"] - ), + ) ] ) @@ -453,18 +453,18 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Baz"]), + MockTarget(name: "Foo", dependencies: ["Baz"]) ], products: [], dependencies: [ - .sourceControl(path: "bazzz", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "bazzz", requirement: .upToNextMajor(from: "1.0.0")) ], toolsVersion: .v5 ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [] ), @@ -472,10 +472,10 @@ final class WorkspaceTests: XCTestCase { name: "Baz", path: "Overridden/bazzz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ] ), ], @@ -484,13 +484,13 @@ final class WorkspaceTests: XCTestCase { name: "Baz", path: "bazzz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.0.1", "1.0.3", "1.0.5", "1.0.8"] - ), + ) ] ) @@ -515,7 +515,7 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: []), + MockTarget(name: "Foo", dependencies: []) ], products: [], dependencies: [] @@ -524,7 +524,7 @@ final class WorkspaceTests: XCTestCase { name: "Foo", path: "Nested/Foo", targets: [ - MockTarget(name: "Foo", dependencies: []), + MockTarget(name: "Foo", dependencies: []) ], products: [], dependencies: [] @@ -556,7 +556,7 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "FooTarget", dependencies: [.product(name: "BarProduct", package: "BarPackage")] - ), + ) ], products: [], dependencies: [ @@ -564,7 +564,7 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar-package", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], toolsVersion: .v5 ), @@ -572,10 +572,10 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar-package", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "1.0.1"] ), @@ -585,13 +585,13 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar-package", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "1.0.1"] - ), + ) ] ) @@ -601,7 +601,7 @@ final class WorkspaceTests: XCTestCase { .localSourceControl( path: "\(sandbox)/pkgs/bar-package", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ] ) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -625,11 +625,11 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["BazAB"]), + MockTarget(name: "Foo", dependencies: ["BazAB"]) ], products: [], dependencies: [ - .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")) ], toolsVersion: .v5 ), @@ -640,7 +640,7 @@ final class WorkspaceTests: XCTestCase { MockTarget(name: "BazB"), ], products: [ - MockProduct(name: "BazAB", modules: ["BazA", "BazB"]), + MockProduct(name: "BazAB", modules: ["BazA", "BazB"]) ] ), ], @@ -648,13 +648,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0"] - ), + ) ] ) @@ -686,11 +686,11 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Baz"]), + MockTarget(name: "Foo", dependencies: ["Baz"]) ], products: [], dependencies: [ - .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")) ] ), MockPackage( @@ -700,7 +700,7 @@ final class WorkspaceTests: XCTestCase { MockTarget(name: "BazB"), ], products: [ - MockProduct(name: "Baz", modules: ["BazA", "BazB"]), + MockProduct(name: "Baz", modules: ["BazA", "BazB"]) ] ), ], @@ -708,13 +708,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0"] - ), + ) ] ) @@ -774,23 +774,23 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar"]), + MockTarget(name: "Foo", dependencies: ["Bar"]) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0"] ), @@ -836,36 +836,36 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "A", targets: [ - MockTarget(name: "A", dependencies: ["AA"]), + MockTarget(name: "A", dependencies: ["AA"]) ], products: [ - MockProduct(name: "A", modules: ["A"]), + MockProduct(name: "A", modules: ["A"]) ], dependencies: [ - .sourceControl(path: "./AA", requirement: .exact("1.0.0")), + .sourceControl(path: "./AA", requirement: .exact("1.0.0")) ], versions: ["1.0.0"] ), MockPackage( name: "A", targets: [ - MockTarget(name: "A", dependencies: ["AA"]), + MockTarget(name: "A", dependencies: ["AA"]) ], products: [ - MockProduct(name: "A", modules: ["A"]), + MockProduct(name: "A", modules: ["A"]) ], dependencies: [ - .sourceControl(path: "./AA", requirement: .exact("2.0.0")), + .sourceControl(path: "./AA", requirement: .exact("2.0.0")) ], versions: ["1.0.1"] ), MockPackage( name: "AA", targets: [ - MockTarget(name: "AA"), + MockTarget(name: "AA") ], products: [ - MockProduct(name: "AA", modules: ["AA"]), + MockProduct(name: "AA", modules: ["AA"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -875,7 +875,7 @@ final class WorkspaceTests: XCTestCase { // Resolve when A = 1.0.0. do { let deps: [MockDependency] = [ - .sourceControl(path: "./A", requirement: .exact("1.0.0"), products: .specific(["A"])), + .sourceControl(path: "./A", requirement: .exact("1.0.0"), products: .specific(["A"])) ] try await workspace.checkPackageGraph(deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -898,7 +898,7 @@ final class WorkspaceTests: XCTestCase { // Resolve when A = 1.0.1. do { let deps: [MockDependency] = [ - .sourceControl(path: "./A", requirement: .exact("1.0.1"), products: .specific(["A"])), + .sourceControl(path: "./A", requirement: .exact("1.0.1"), products: .specific(["A"])) ] try await workspace.checkPackageGraph(deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -938,36 +938,36 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "A", targets: [ - MockTarget(name: "A", dependencies: ["AA"]), + MockTarget(name: "A", dependencies: ["AA"]) ], products: [ - MockProduct(name: "A", modules: ["A"]), + MockProduct(name: "A", modules: ["A"]) ], dependencies: [ - .sourceControl(path: "./AA", requirement: .exact("1.0.0")), + .sourceControl(path: "./AA", requirement: .exact("1.0.0")) ], versions: ["1.0.0"] ), MockPackage( name: "B", targets: [ - MockTarget(name: "B", dependencies: ["AA"]), + MockTarget(name: "B", dependencies: ["AA"]) ], products: [ - MockProduct(name: "B", modules: ["B"]), + MockProduct(name: "B", modules: ["B"]) ], dependencies: [ - .sourceControl(path: "./AA", requirement: .exact("2.0.0")), + .sourceControl(path: "./AA", requirement: .exact("2.0.0")) ], versions: ["1.0.0"] ), MockPackage( name: "AA", targets: [ - MockTarget(name: "AA"), + MockTarget(name: "AA") ], products: [ - MockProduct(name: "AA", modules: ["AA"]), + MockProduct(name: "AA", modules: ["AA"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -1002,7 +1002,7 @@ final class WorkspaceTests: XCTestCase { name: "A", targets: [MockTarget(name: "A")], products: [] - ), + ) ], packages: [] ) @@ -1023,7 +1023,7 @@ final class WorkspaceTests: XCTestCase { resolvedPackages: [bRef: v1_5, cRef: v2], managedDependencies: [ bPackagePath: .sourceControlCheckout(packageRef: bRef, state: v1_5, subpath: bPath) - .edited(subpath: bPath, unmanagedPath: .none), + .edited(subpath: bPath, unmanagedPath: .none) ] ) @@ -1036,7 +1036,7 @@ final class WorkspaceTests: XCTestCase { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") - let v1Requirement: SourceControlRequirement = .range("1.0.0" ..< "2.0.0") + let v1Requirement: SourceControlRequirement = .range("1.0.0"..<"2.0.0") let v1 = CheckoutState.version("1.0.0", revision: Revision(identifier: "hello")) let workspace = try await MockWorkspace( @@ -1051,7 +1051,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./B", requirement: v1Requirement), .sourceControl(path: "./C", requirement: v1Requirement), ] - ), + ) ], packages: [ MockPackage( @@ -1084,7 +1084,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.set( resolvedPackages: [bRef: v1], managedDependencies: [ - bPackagePath: .sourceControlCheckout(packageRef: bRef, state: v1, subpath: bPath), + bPackagePath: .sourceControlCheckout(packageRef: bRef, state: v1, subpath: bPath) ] ) @@ -1098,7 +1098,7 @@ final class WorkspaceTests: XCTestCase { let fs = InMemoryFileSystem() let bPath = RelativePath("B") let cPath = RelativePath("C") - let v1Requirement: SourceControlRequirement = .range("1.0.0" ..< "2.0.0") + let v1Requirement: SourceControlRequirement = .range("1.0.0"..<"2.0.0") let branchRequirement: SourceControlRequirement = .branch("master") let v1_5 = CheckoutState.version("1.0.5", revision: Revision(identifier: "hello")) @@ -1114,7 +1114,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./B", requirement: v1Requirement), .sourceControl(path: "./C", requirement: branchRequirement), ] - ), + ) ], packages: [ MockPackage( @@ -1154,11 +1154,16 @@ final class WorkspaceTests: XCTestCase { let result = try await workspace.checkPrecomputeResolution() XCTAssertNoDiagnostics(result.diagnostics) - XCTAssertEqual(result.result, .required(reason: .packageRequirementChange( - package: cRef, - state: .sourceControlCheckout(v1_5), - requirement: .revision("master") - ))) + XCTAssertEqual( + result.result, + .required( + reason: .packageRequirementChange( + package: cRef, + state: .sourceControlCheckout(v1_5), + requirement: .revision("master") + ) + ) + ) } func testPrecomputeResolution_requirementChange_versionToRevision() async throws { @@ -1176,9 +1181,9 @@ final class WorkspaceTests: XCTestCase { targets: [MockTarget(name: "A")], products: [], dependencies: [ - .sourceControl(path: "./C", requirement: .revision("hello")), + .sourceControl(path: "./C", requirement: .revision("hello")) ] - ), + ) ], packages: [ MockPackage( @@ -1186,7 +1191,7 @@ final class WorkspaceTests: XCTestCase { targets: [MockTarget(name: "C")], products: [MockProduct(name: "C", modules: ["C"])], versions: [nil, "1.0.0", "1.0.5", "2.0.0"] - ), + ) ] ) @@ -1199,24 +1204,29 @@ final class WorkspaceTests: XCTestCase { try await testWorkspace.set( resolvedPackages: [cRef: v1_5], managedDependencies: [ - cPackagePath: .sourceControlCheckout(packageRef: cRef, state: v1_5, subpath: cPath), + cPackagePath: .sourceControlCheckout(packageRef: cRef, state: v1_5, subpath: cPath) ] ) let result = try await testWorkspace.checkPrecomputeResolution() XCTAssertNoDiagnostics(result.diagnostics) - XCTAssertEqual(result.result, .required(reason: .packageRequirementChange( - package: cRef, - state: .sourceControlCheckout(v1_5), - requirement: .revision("hello") - ))) + XCTAssertEqual( + result.result, + .required( + reason: .packageRequirementChange( + package: cRef, + state: .sourceControlCheckout(v1_5), + requirement: .revision("hello") + ) + ) + ) } func testPrecomputeResolution_requirementChange_localToBranch() async throws { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") - let v1Requirement: SourceControlRequirement = .range("1.0.0" ..< "2.0.0") + let v1Requirement: SourceControlRequirement = .range("1.0.0"..<"2.0.0") let masterRequirement: SourceControlRequirement = .branch("master") let v1_5 = CheckoutState.version("1.0.5", revision: Revision(identifier: "hello")) @@ -1232,7 +1242,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./B", requirement: v1Requirement), .sourceControl(path: "./C", requirement: masterRequirement), ] - ), + ) ], packages: [ MockPackage( @@ -1272,11 +1282,16 @@ final class WorkspaceTests: XCTestCase { let result = try await workspace.checkPrecomputeResolution() XCTAssertNoDiagnostics(result.diagnostics) - XCTAssertEqual(result.result, .required(reason: .packageRequirementChange( - package: cRef, - state: .fileSystem(cPackagePath), - requirement: .revision("master") - ))) + XCTAssertEqual( + result.result, + .required( + reason: .packageRequirementChange( + package: cRef, + state: .fileSystem(cPackagePath), + requirement: .revision("master") + ) + ) + ) } func testPrecomputeResolution_requirementChange_versionToLocal() async throws { @@ -1284,7 +1299,7 @@ final class WorkspaceTests: XCTestCase { let fs = InMemoryFileSystem() let bPath = RelativePath("B") let cPath = RelativePath("C") - let v1Requirement: SourceControlRequirement = .range("1.0.0" ..< "2.0.0") + let v1Requirement: SourceControlRequirement = .range("1.0.0"..<"2.0.0") let v1_5 = CheckoutState.version("1.0.5", revision: Revision(identifier: "hello")) let workspace = try await MockWorkspace( @@ -1299,7 +1314,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./B", requirement: v1Requirement), .fileSystem(path: "./C"), ] - ), + ) ], packages: [ MockPackage( @@ -1339,11 +1354,16 @@ final class WorkspaceTests: XCTestCase { let result = try await workspace.checkPrecomputeResolution() XCTAssertNoDiagnostics(result.diagnostics) - XCTAssertEqual(result.result, .required(reason: .packageRequirementChange( - package: cRef, - state: .sourceControlCheckout(v1_5), - requirement: .unversioned - ))) + XCTAssertEqual( + result.result, + .required( + reason: .packageRequirementChange( + package: cRef, + state: .sourceControlCheckout(v1_5), + requirement: .unversioned + ) + ) + ) } func testPrecomputeResolution_requirementChange_branchToLocal() async throws { @@ -1351,7 +1371,7 @@ final class WorkspaceTests: XCTestCase { let fs = InMemoryFileSystem() let bPath = RelativePath("B") let cPath = RelativePath("C") - let v1Requirement: SourceControlRequirement = .range("1.0.0" ..< "2.0.0") + let v1Requirement: SourceControlRequirement = .range("1.0.0"..<"2.0.0") let v1_5 = CheckoutState.version("1.0.5", revision: Revision(identifier: "hello")) let master = CheckoutState.branch(name: "master", revision: Revision(identifier: "master")) @@ -1367,7 +1387,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./B", requirement: v1Requirement), .fileSystem(path: "./C"), ] - ), + ) ], packages: [ MockPackage( @@ -1407,11 +1427,16 @@ final class WorkspaceTests: XCTestCase { let result = try await workspace.checkPrecomputeResolution() XCTAssertNoDiagnostics(result.diagnostics) - XCTAssertEqual(result.result, .required(reason: .packageRequirementChange( - package: cRef, - state: .sourceControlCheckout(master), - requirement: .unversioned - ))) + XCTAssertEqual( + result.result, + .required( + reason: .packageRequirementChange( + package: cRef, + state: .sourceControlCheckout(master), + requirement: .unversioned + ) + ) + ) } func testPrecomputeResolution_other() async throws { @@ -1419,8 +1444,8 @@ final class WorkspaceTests: XCTestCase { let fs = InMemoryFileSystem() let bPath = RelativePath("B") let cPath = RelativePath("C") - let v1Requirement: SourceControlRequirement = .range("1.0.0" ..< "2.0.0") - let v2Requirement: SourceControlRequirement = .range("2.0.0" ..< "3.0.0") + let v1Requirement: SourceControlRequirement = .range("1.0.0"..<"2.0.0") + let v2Requirement: SourceControlRequirement = .range("2.0.0"..<"3.0.0") let v1_5 = CheckoutState.version("1.0.5", revision: Revision(identifier: "hello")) let workspace = try await MockWorkspace( @@ -1435,7 +1460,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./B", requirement: v1Requirement), .sourceControl(path: "./C", requirement: v2Requirement), ] - ), + ) ], packages: [ MockPackage( @@ -1477,9 +1502,11 @@ final class WorkspaceTests: XCTestCase { XCTAssertNoDiagnostics(result.diagnostics) XCTAssertEqual( result.result, - .required(reason: .other( - "Dependencies could not be resolved because no versions of \'c\' match the requirement 2.0.0..<3.0.0 and root depends on \'c\' 2.0.0..<3.0.0." - )) + .required( + reason: .other( + "Dependencies could not be resolved because no versions of \'c\' match the requirement 2.0.0..<3.0.0 and root depends on \'c\' 2.0.0..<3.0.0." + ) + ) ) } @@ -1488,8 +1515,8 @@ final class WorkspaceTests: XCTestCase { let fs = InMemoryFileSystem() let bPath = RelativePath("B") let cPath = RelativePath("C") - let v1Requirement: SourceControlRequirement = .range("1.0.0" ..< "2.0.0") - let v2Requirement: SourceControlRequirement = .range("2.0.0" ..< "3.0.0") + let v1Requirement: SourceControlRequirement = .range("1.0.0"..<"2.0.0") + let v2Requirement: SourceControlRequirement = .range("2.0.0"..<"3.0.0") let v1_5 = CheckoutState.version("1.0.5", revision: Revision(identifier: "hello")) let v2 = CheckoutState.version("2.0.0", revision: Revision(identifier: "hello")) @@ -1505,7 +1532,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./B", requirement: v1Requirement), .sourceControl(path: "./C", requirement: v2Requirement), ] - ), + ) ], packages: [ MockPackage( @@ -1583,47 +1610,47 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [ - MockProduct(name: "Root", modules: ["Root"]), + MockProduct(name: "Root", modules: ["Root"]) ], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar"]), + MockTarget(name: "Foo", dependencies: ["Bar"]) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.5.0"] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0"] ), @@ -1632,7 +1659,7 @@ final class WorkspaceTests: XCTestCase { // Do an initial run, capping at Foo at 1.0.0. let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -1684,34 +1711,34 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [ - MockProduct(name: "Root", modules: ["Root"]), + MockProduct(name: "Root", modules: ["Root"]) ], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] ), MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.5.0"] ), @@ -1720,7 +1747,7 @@ final class WorkspaceTests: XCTestCase { // Do an initial run, capping at Foo at 1.0.0. let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in @@ -1738,14 +1765,14 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkUpdateDryRun(roots: ["Root"]) { changes, diagnostics in XCTAssertNoDiagnostics(diagnostics) #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - let stateChange = Workspace.PackageStateChange - .updated(.init(requirement: .version(Version("1.5.0")), products: .specific(["Foo"]))) + let stateChange = Workspace.PackageStateChange + .updated(.init(requirement: .version(Version("1.5.0")), products: .specific(["Foo"]))) #else - let stateChange = Workspace.PackageStateChange - .updated(.init(requirement: .version(Version("1.5.0")), products: .everything)) + let stateChange = Workspace.PackageStateChange + .updated(.init(requirement: .version(Version("1.5.0")), products: .everything)) #endif - let path = sandbox.appending(components: ["pkgs","Foo"]) + let path = sandbox.appending(components: ["pkgs", "Foo"]) let expectedChange = ( PackageReference.localSourceControl(identity: PackageIdentity(path: path), path: path), stateChange @@ -1779,50 +1806,50 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [ - MockProduct(name: "Root", modules: ["Root"]), + MockProduct(name: "Root", modules: ["Root"]) ], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar"]), + MockTarget(name: "Foo", dependencies: ["Bar"]) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.5.0"] ), MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar"]), + MockTarget(name: "Foo", dependencies: ["Bar"]) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMinor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMinor(from: "1.0.0")) ], versions: ["1.0.0"] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.2.0"] ), @@ -1831,7 +1858,7 @@ final class WorkspaceTests: XCTestCase { // Do an initial run, capping at Foo at 1.0.0. let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -1883,27 +1910,27 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [ - MockProduct(name: "Root", modules: ["Root"]), + MockProduct(name: "Root", modules: ["Root"]) ], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ] ) @@ -1962,21 +1989,21 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root1", targets: [ - MockTarget(name: "Root1", dependencies: ["Foo"]), + MockTarget(name: "Root1", dependencies: ["Foo"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] ), MockPackage( name: "Root2", targets: [ - MockTarget(name: "Root2", dependencies: ["Bar"]), + MockTarget(name: "Root2", dependencies: ["Bar"]) ], products: [], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ] ), ], @@ -2041,7 +2068,7 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root1", targets: [ - MockTarget(name: "Root1", dependencies: ["Foo", "Bar", "Baz", "Bam"]), + MockTarget(name: "Root1", dependencies: ["Foo", "Bar", "Baz", "Bam"]) ], products: [], dependencies: [ @@ -2050,16 +2077,16 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Bam", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar", "Baz"]), + MockTarget(name: "Foo", dependencies: ["Bar", "Baz"]) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), @@ -2071,13 +2098,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz", dependencies: ["Bam"]), + MockTarget(name: "Baz", dependencies: ["Bam"]) ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], dependencies: [ - .sourceControl(path: "./Bam", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bam", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -2110,32 +2137,32 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .branch("develop")), + .sourceControl(path: "./Foo", requirement: .branch("develop")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["develop"] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["boo"] ), @@ -2148,7 +2175,7 @@ final class WorkspaceTests: XCTestCase { // We request Bar via revision. let deps: [MockDependency] = [ - .sourceControl(path: "./Bar", requirement: .revision(barRevision), products: .specific(["Bar"])), + .sourceControl(path: "./Bar", requirement: .revision(barRevision), products: .specific(["Bar"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -2174,25 +2201,25 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.2.3"] - ), + ) ] ) @@ -2247,16 +2274,16 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ - .genericPackage(named: "Foo"), + .genericPackage(named: "Foo") ] ) @@ -2293,26 +2320,26 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"], toolsVersion: .v3 - ), + ) ] ) @@ -2334,21 +2361,21 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [] ), MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [] ), @@ -2402,7 +2429,6 @@ final class WorkspaceTests: XCTestCase { } } - func testEditDependency() async throws { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2414,33 +2440,33 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo", "Bar"]), + MockTarget(name: "Root", dependencies: ["Foo", "Bar"]) ], products: [], dependencies: [ .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", nil] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", nil] ), @@ -2526,16 +2552,16 @@ final class WorkspaceTests: XCTestCase { name: "Root", dependencies: ["Foo"], settings: [ - .init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"])), + .init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"])) ] - ), + ) ], products: [], dependencies: [ // Must be a branch or revision for unsafe flags - .sourceControl(path: "./Foo", requirement: .revision("1.0.0")), + .sourceControl(path: "./Foo", requirement: .revision("1.0.0")) ] - ), + ) ], packages: [ MockPackage( @@ -2544,15 +2570,15 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "Foo", settings: [ - .init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"])), + .init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"])) ] - ), + ) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", nil] - ), + ) ] ) @@ -2585,25 +2611,25 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", nil] - ), + ) ] ) @@ -2649,18 +2675,18 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", nil] - ), + ) ] ) let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])) ] let ws = try workspace.getOrCreateWorkspace() @@ -2722,33 +2748,33 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo", "Bar"]), + MockTarget(name: "Root", dependencies: ["Foo", "Bar"]) ], products: [], dependencies: [ .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.2.0", "1.3.2"] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", nil] ), @@ -2756,7 +2782,7 @@ final class WorkspaceTests: XCTestCase { ) let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])) ] // Load the graph. try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in @@ -2843,45 +2869,45 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] ), MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar"]), + MockTarget(name: "Foo", dependencies: ["Bar"]) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: [nil] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0"] ), @@ -2901,7 +2927,7 @@ final class WorkspaceTests: XCTestCase { } let deps: [MockDependency] = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + .fileSystem(path: "./Foo", products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -2928,27 +2954,27 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar"]), + MockTarget(name: "Foo", dependencies: ["Bar"]) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .exact("1.0.0")), + .sourceControl(path: "./Bar", requirement: .exact("1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0"] - ), + ) ] ) @@ -3014,32 +3040,32 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", nil] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", nil] ), @@ -3079,7 +3105,7 @@ final class WorkspaceTests: XCTestCase { // Try resolving a bad graph. let deps: [MockDependency] = [ - .sourceControl(path: "./Bar", requirement: .exact("1.1.0"), products: .specific(["Bar"])), + .sourceControl(path: "./Bar", requirement: .exact("1.1.0"), products: .specific(["Bar"])) ] // Replicate earlier workspace, include Bar dependency in target so that dependency resolution can include it. @@ -3090,32 +3116,32 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo", "Bar"]), + MockTarget(name: "Root", dependencies: ["Foo", "Bar"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", nil] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", nil] ), @@ -3139,26 +3165,29 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: [ - .product(name: "Foo", package: "foo"), - .product(name: "Bar", package: "bar"), - ]), + MockTarget( + name: "Root", + dependencies: [ + .product(name: "Foo", package: "foo"), + .product(name: "Bar", package: "bar"), + ] + ) ], dependencies: [ .sourceControl(url: "https://scm.com/org/foo", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(url: "https://scm.com/org/bar", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Foo", url: "https://scm.com/org/foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: [nil, "1.0.0", "1.1.0"] ), @@ -3166,10 +3195,10 @@ final class WorkspaceTests: XCTestCase { name: "Bar", url: "https://scm.com/org/bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.1.0", "1.2.0"] ), @@ -3230,27 +3259,27 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [ - MockProduct(name: "Root", modules: ["Root"]), + MockProduct(name: "Root", modules: ["Root"]) ], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.5.0"] - ), + ) ], skipDependenciesUpdates: true ) @@ -3287,29 +3316,29 @@ final class WorkspaceTests: XCTestCase { .fileSystem(path: "./Bar"), .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0", nil] ), MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz", dependencies: ["Bar"]), + MockTarget(name: "Baz", dependencies: ["Bar"]) ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0", "1.5.0"] ), @@ -3346,7 +3375,6 @@ final class WorkspaceTests: XCTestCase { } } - func testLocalDependencyTransitive() async throws { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3363,31 +3391,31 @@ final class WorkspaceTests: XCTestCase { ], products: [], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar", dependencies: ["Baz"]), + MockTarget(name: "Bar", dependencies: ["Baz"]) ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], dependencies: [ - .fileSystem(path: "./Baz"), + .fileSystem(path: "./Baz") ], versions: ["1.0.0", "1.5.0", nil] ), MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.5.0", nil] ), @@ -3420,25 +3448,25 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar"]), + MockTarget(name: "Foo", dependencies: ["Bar"]) ], products: [], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0", nil] - ), + ) ] ) @@ -3455,7 +3483,7 @@ final class WorkspaceTests: XCTestCase { // Override with local package and run update. let deps: [MockDependency] = [ - .fileSystem(path: "./Bar", products: .specific(["Bar"])), + .fileSystem(path: "./Bar", products: .specific(["Bar"])) ] try await workspace.checkUpdate(roots: ["Foo"], deps: deps) { diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3484,16 +3512,15 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: []), + MockTarget(name: "Foo", dependencies: []) ], products: [], dependencies: [ - .fileSystem(path: "Bar"), + .fileSystem(path: "Bar") ] - ), + ) ], - packages: [ - ] + packages: [] ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in @@ -3524,23 +3551,23 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: []), + MockTarget(name: "Root", dependencies: []) ], products: [], dependencies: [] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["develop", "1.0.0"] - ), + ) ] ) @@ -3548,7 +3575,7 @@ final class WorkspaceTests: XCTestCase { // without running swift package update. var deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .branch("develop"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .branch("develop"), products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -3562,7 +3589,7 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3572,7 +3599,7 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .sourceControl(path: "./Foo", requirement: .branch("develop"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .branch("develop"), products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3593,23 +3620,23 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: []), + MockTarget(name: "Root", dependencies: []) ], products: [], dependencies: [] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["develop", "1.0.0", nil] - ), + ) ] ) @@ -3617,7 +3644,7 @@ final class WorkspaceTests: XCTestCase { // without running swift package update. var deps: [MockDependency] = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + .fileSystem(path: "./Foo", products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -3631,7 +3658,7 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3641,7 +3668,7 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + .fileSystem(path: "./Foo", products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3662,20 +3689,20 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: []), + MockTarget(name: "Root", dependencies: []) ], products: [], dependencies: [] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: [nil] ), @@ -3683,10 +3710,10 @@ final class WorkspaceTests: XCTestCase { name: "Foo", path: "Foo2", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: [nil] ), @@ -3697,7 +3724,7 @@ final class WorkspaceTests: XCTestCase { // different locations works correctly. var deps: [MockDependency] = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + .fileSystem(path: "./Foo", products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -3711,7 +3738,7 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .fileSystem(path: "./Foo2", products: .specific(["Foo"])), + .fileSystem(path: "./Foo2", products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3734,20 +3761,20 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: []), + MockTarget(name: "Root", dependencies: []) ], products: [], dependencies: [] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: [nil] ), @@ -3755,10 +3782,10 @@ final class WorkspaceTests: XCTestCase { name: "Foo", path: "Nested/Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: [nil] ), @@ -3766,7 +3793,7 @@ final class WorkspaceTests: XCTestCase { ) var deps: [MockDependency] = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + .fileSystem(path: "./Foo", products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -3784,7 +3811,7 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .fileSystem(path: "./Nested/Foo", products: .specific(["Foo"])), + .fileSystem(path: "./Nested/Foo", products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3811,21 +3838,21 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: []), + MockTarget(name: "Root", dependencies: []) ], products: [], dependencies: [] - ), + ) ], packages: [ MockPackage( name: "Foo", url: "https://scm.com/org/foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] ), @@ -3833,10 +3860,10 @@ final class WorkspaceTests: XCTestCase { name: "Foo", url: "https://scm.com/other/foo", targets: [ - MockTarget(name: "OtherFoo"), + MockTarget(name: "OtherFoo") ], products: [ - MockProduct(name: "OtherFoo", modules: ["OtherFoo"]), + MockProduct(name: "OtherFoo", modules: ["OtherFoo"]) ], versions: ["1.1.0"] ), @@ -3844,7 +3871,7 @@ final class WorkspaceTests: XCTestCase { ) var deps: [MockDependency] = [ - .sourceControl(url: "https://scm.com/org/foo", requirement: .exact("1.0.0")), + .sourceControl(url: "https://scm.com/org/foo", requirement: .exact("1.0.0")) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3863,7 +3890,7 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .sourceControl(url: "https://scm.com/other/foo", requirement: .exact("1.1.0")), + .sourceControl(url: "https://scm.com/other/foo", requirement: .exact("1.1.0")) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3889,28 +3916,28 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: []), + MockTarget(name: "Root", dependencies: []) ], products: [], dependencies: [] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ] ) let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])), + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3948,7 +3975,7 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root1", targets: [ - MockTarget(name: "Root1", dependencies: ["Foo"]), + MockTarget(name: "Root1", dependencies: ["Foo"]) ], products: [], dependencies: [ @@ -3956,14 +3983,14 @@ final class WorkspaceTests: XCTestCase { path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"]) - ), + ) ], toolsVersion: pair.0 ), MockPackage( name: "Root2", targets: [ - MockTarget(name: "Root2", dependencies: []), + MockTarget(name: "Root2", dependencies: []) ], products: [], dependencies: [], @@ -3974,13 +4001,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ] ) @@ -4016,72 +4043,72 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: []), + MockTarget(name: "Root", dependencies: []) ], products: [], dependencies: [] - ), + ) ], packages: [ MockPackage( name: "Foo", url: "https://localhost/org/foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.1.0"], - revisionProvider: { version in version } // stable revisions + revisionProvider: { version in version } // stable revisions ), MockPackage( name: "Bar", url: "https://localhost/org/bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.1.0"], - revisionProvider: { version in version } // stable revisions + revisionProvider: { version in version } // stable revisions ), MockPackage( name: "Foo", - url: "https://localhost/ORG/FOO", // diff: case + url: "https://localhost/ORG/FOO", // diff: case targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.1.0"], - revisionProvider: { version in version } // stable revisions + revisionProvider: { version in version } // stable revisions ), MockPackage( name: "Foo", - url: "https://localhost/org/foo.git", // diff: .git extension + url: "https://localhost/org/foo.git", // diff: .git extension targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.1.0"], - revisionProvider: { version in version } // stable revisions + revisionProvider: { version in version } // stable revisions ), MockPackage( name: "Bar", - url: "https://localhost/org/bar.git", // diff: .git extension + url: "https://localhost/org/bar.git", // diff: .git extension targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.1.0"], - revisionProvider: { version in version } // stable revisions + revisionProvider: { version in version } // stable revisions ), ] ) @@ -4264,7 +4291,7 @@ final class WorkspaceTests: XCTestCase { .product(name: "Foo", package: "foo"), .product(name: "Bar", package: "bar"), ] - ), + ) ], products: [], dependencies: [ @@ -4272,17 +4299,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(url: "https://localhost/org/bar", requirement: .upToNextMinor(from: "1.1.0")), ], toolsVersion: .v5_10 - ), + ) ], packages: [ MockPackage( name: "Foo", url: "https://localhost/org/foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.0.1", "1.1.0", "1.1.1", "1.2.0", "1.2.1", "1.3.0", "1.3.1"] ), @@ -4290,10 +4317,10 @@ final class WorkspaceTests: XCTestCase { name: "Bar", url: "https://localhost/org/bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.0.1", "1.1.0", "1.1.1", "1.2.0", "1.2.1", "1.3.0", "1.3.1"] ), @@ -4301,10 +4328,10 @@ final class WorkspaceTests: XCTestCase { name: "Baz", url: "https://localhost/org/baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.0.1", "1.1.0", "1.1.1", "1.2.0", "1.2.1", "1.3.0", "1.3.1"] ), @@ -4417,7 +4444,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.closeWorkspace(resetResolvedFile: false) // change the dependency requirements let changedDeps: [PackageDependency] = [ - .remoteSourceControl(url: "https://localhost/org/baz", requirement: .upToNextMinor(from: "1.0.0")), + .remoteSourceControl(url: "https://localhost/org/baz", requirement: .upToNextMinor(from: "1.0.0")) ] // run resolution again, but change requirements try await workspace.checkPackageGraph(roots: ["Root"], dependencies: changedDeps) { graph, diagnostics in @@ -4536,29 +4563,35 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "Dep", package: "dep"), - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "Dep", package: "dep") + ] + ) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(path: "./Dep", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Dep", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Dep", targets: [ - MockTarget(name: "Dep", dependencies: [ - .product(name: "Bar", package: "bar"), - .product(name: "Baz", package: "baz"), - ]), + MockTarget( + name: "Dep", + dependencies: [ + .product(name: "Bar", package: "bar"), + .product(name: "Baz", package: "baz"), + ] + ) ], products: [ - MockProduct(name: "Dep", modules: ["Dep"]), + MockProduct(name: "Dep", modules: ["Dep"]) ], dependencies: [ .sourceControl(path: "Bar", requirement: .upToNextMajor(from: "1.0.0")), @@ -4569,20 +4602,20 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "BarMirror", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0"] ), MockPackage( name: "BazMirror", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.6.0"] ), @@ -4628,61 +4661,67 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "Dep", package: "dep"), - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "Dep", package: "dep") + ] + ) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(path: "./Dep", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Dep", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Dep", targets: [ - MockTarget(name: "Dep", dependencies: [ - .product(name: "Bar", package: "bar"), - ]), + MockTarget( + name: "Dep", + dependencies: [ + .product(name: "Bar", package: "bar") + ] + ) ], products: [ - MockProduct(name: "Dep", modules: ["Dep"]), + MockProduct(name: "Dep", modules: ["Dep"]) ], dependencies: [ - .sourceControl(path: "Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "Bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0", "1.4.0"] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0"] ), MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.6.0"] ), MockPackage( name: "BarMirror", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0"] ), @@ -4691,7 +4730,7 @@ final class WorkspaceTests: XCTestCase { ) let deps: [MockDependency] = [ - .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Baz"])), + .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Baz"])) ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in @@ -4725,30 +4764,36 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "Dep", package: "dep"), - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "Dep", package: "dep") + ] + ) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(url: "https://scm.com/org/dep", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://scm.com/org/dep", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Dep", url: "https://scm.com/org/dep", targets: [ - MockTarget(name: "Dep", dependencies: [ - .product(name: "Bar", package: "bar"), - .product(name: "Baz", package: "baz"), - ]), + MockTarget( + name: "Dep", + dependencies: [ + .product(name: "Bar", package: "bar"), + .product(name: "Baz", package: "baz"), + ] + ) ], products: [ - MockProduct(name: "Dep", modules: ["Dep"]), + MockProduct(name: "Dep", modules: ["Dep"]) ], dependencies: [ .sourceControl(url: "https://scm.com/org/bar", requirement: .upToNextMajor(from: "1.0.0")), @@ -4760,10 +4805,10 @@ final class WorkspaceTests: XCTestCase { name: "BarMirror", url: "https://scm.com/org/bar-mirror", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0"] ), @@ -4771,10 +4816,10 @@ final class WorkspaceTests: XCTestCase { name: "BazMirror", url: "https://scm.com/org/baz-mirror", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.6.0"] ), @@ -4814,32 +4859,38 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "Dep", package: "dep"), - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "Dep", package: "dep") + ] + ) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(url: "https://scm.com/org/dep", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://scm.com/org/dep", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Dep", url: "https://scm.com/org/dep", targets: [ - MockTarget(name: "Dep", dependencies: [ - .product(name: "Bar", package: "bar"), - ]), + MockTarget( + name: "Dep", + dependencies: [ + .product(name: "Bar", package: "bar") + ] + ) ], products: [ - MockProduct(name: "Dep", modules: ["Dep"]), + MockProduct(name: "Dep", modules: ["Dep"]) ], dependencies: [ - .sourceControl(url: "https://scm.com/org/bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://scm.com/org/bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0", "1.4.0"] ), @@ -4847,10 +4898,10 @@ final class WorkspaceTests: XCTestCase { name: "Bar", url: "https://scm.com/org/bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0"] ), @@ -4858,10 +4909,10 @@ final class WorkspaceTests: XCTestCase { name: "Baz", url: "https://scm.com/org/baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.6.0"] ), @@ -4869,10 +4920,10 @@ final class WorkspaceTests: XCTestCase { name: "BarMirror", url: "https://scm.com/org/bar-mirror", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0"] ), @@ -4885,7 +4936,7 @@ final class WorkspaceTests: XCTestCase { url: "https://scm.com/org/baz", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Baz"]) - ), + ) ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in @@ -4918,29 +4969,32 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "Bar", package: "bar"), - .product(name: "Baz", package: "baz"), - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "Bar", package: "bar"), + .product(name: "Baz", package: "baz"), + ] + ) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ .sourceControl(url: "https://scm.com/org/bar", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(url: "https://scm.com/org/baz", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "BarMirror", identity: "org.bar-mirror", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0"] ), @@ -4948,10 +5002,10 @@ final class WorkspaceTests: XCTestCase { name: "Baz", url: "https://scm.com/org/baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.6.0"] ), @@ -4988,29 +5042,32 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "Bar", package: "org.bar"), - .product(name: "Baz", package: "org.baz"), - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "Bar", package: "org.bar"), + .product(name: "Baz", package: "org.baz"), + ] + ) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ .registry(identity: "org.bar", requirement: .upToNextMajor(from: "1.0.0")), .registry(identity: "org.baz", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "BarMirror", url: "https://scm.com/org/bar-mirror", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "1.5.0"] ), @@ -5018,10 +5075,10 @@ final class WorkspaceTests: XCTestCase { name: "Baz", identity: "org.baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.6.0"] ), @@ -5065,15 +5122,15 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "Root", dependencies: [ - .product(name: "Bar", package: "bar"), + .product(name: "Bar", package: "bar") ] - ), + ) ], products: [], dependencies: [ - .sourceControl(url: "https://scm.com/org/bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://scm.com/org/bar", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( @@ -5083,15 +5140,15 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "Bar", dependencies: [ - .product(name: "Foo", package: "foo"), + .product(name: "Foo", package: "foo") ] - ), + ) ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], dependencies: [ - .sourceControl(url: "https://scm.com/org/foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://scm.com/org/foo", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -5102,15 +5159,15 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "Bar", dependencies: [ - .product(name: "OtherFoo", package: "foo"), + .product(name: "OtherFoo", package: "foo") ] - ), + ) ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], dependencies: [ - .sourceControl(url: "https://scm.com/other/foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://scm.com/other/foo", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.1.0"], toolsVersion: .v5 @@ -5119,10 +5176,10 @@ final class WorkspaceTests: XCTestCase { name: "Foo", url: "https://scm.com/org/foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"], revisionProvider: { _ in fooRevision } @@ -5131,10 +5188,10 @@ final class WorkspaceTests: XCTestCase { name: "Foo", url: "https://scm.com/other/foo", targets: [ - MockTarget(name: "OtherFoo"), + MockTarget(name: "OtherFoo") ], products: [ - MockProduct(name: "OtherFoo", modules: ["OtherFoo"]), + MockProduct(name: "OtherFoo", modules: ["OtherFoo"]) ], versions: ["1.0.0"], revisionProvider: { _ in fooRevision } @@ -5143,7 +5200,7 @@ final class WorkspaceTests: XCTestCase { ) var deps: [MockDependency] = [ - .sourceControl(url: "https://scm.com/org/bar", requirement: .exact("1.0.0")), + .sourceControl(url: "https://scm.com/org/bar", requirement: .exact("1.0.0")) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -5173,7 +5230,7 @@ final class WorkspaceTests: XCTestCase { await workspace.checkReset { XCTAssertNoDiagnostics($0) } deps = [ - .sourceControl(url: "https://scm.com/org/bar", requirement: .exact("1.1.0")), + .sourceControl(url: "https://scm.com/org/bar", requirement: .exact("1.1.0")) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -5211,33 +5268,33 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo", "Bar"]), + MockTarget(name: "Root", dependencies: ["Foo", "Bar"]) ], products: [], dependencies: [ .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.2.0", "1.3.2"] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "develop"] ), @@ -5246,7 +5303,7 @@ final class WorkspaceTests: XCTestCase { // Load the initial graph. let deps: [MockDependency] = [ - .sourceControl(path: "./Bar", requirement: .revision("develop"), products: .specific(["Bar"])), + .sourceControl(path: "./Bar", requirement: .revision("develop"), products: .specific(["Bar"])) ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -5270,10 +5327,14 @@ final class WorkspaceTests: XCTestCase { ) let fooRepo = try workspace.repositoryProvider - .specifierMap[RepositorySpecifier(path: AbsolutePath( - validating: fooPin.packageRef - .locationString - ))]! + .specifierMap[ + RepositorySpecifier( + path: AbsolutePath( + validating: fooPin.packageRef + .locationString + ) + ) + ]! let revision = try fooRepo.resolveRevision(tag: "1.0.0") let newState = ResolvedPackagesStore.ResolutionState.version("1.0.0", revision: revision.identifier) @@ -5337,7 +5398,7 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo", "Bar"]), + MockTarget(name: "Root", dependencies: ["Foo", "Bar"]) ], products: [], dependencies: [ @@ -5348,10 +5409,10 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ] ), ], @@ -5359,13 +5420,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.2.0", "1.3.2"] - ), + ) ] ) @@ -5388,33 +5449,33 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo", "Bar"]), + MockTarget(name: "Root", dependencies: ["Foo", "Bar"]) ], products: [], dependencies: [ .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.2.0", "1.3.2"] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", "develop"] ), @@ -5445,25 +5506,25 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [], dependencies: [ - .fileSystem(path: "./Foo"), + .fileSystem(path: "./Foo") ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: [nil] - ), + ) ] ) @@ -5486,23 +5547,23 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root"), + MockTarget(name: "Root") ], products: [], dependencies: [] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: [nil] - ), + ) ] ) @@ -5587,35 +5648,35 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo"]), + MockTarget(name: "Root", dependencies: ["Foo"]) ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .branch("develop")), + .sourceControl(path: "./Foo", requirement: .branch("develop")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Local"]), + MockTarget(name: "Foo", dependencies: ["Local"]) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .fileSystem(path: "./Local"), + .fileSystem(path: "./Local") ], versions: ["develop"] ), MockPackage( name: "Local", targets: [ - MockTarget(name: "Local"), + MockTarget(name: "Local") ], products: [ - MockProduct(name: "Local", modules: ["Local"]), + MockProduct(name: "Local", modules: ["Local"]) ], versions: [nil] ), @@ -5646,30 +5707,30 @@ final class WorkspaceTests: XCTestCase { name: "Baz", path: "Overridden/bazzz-master", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ] - ), + ) ], packages: [ MockPackage( name: "Baz", path: "bazzz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0"] - ), + ) ] ) let deps: [MockDependency] = [ - .sourceControl(path: "./bazzz", requirement: .exact("1.0.0"), products: .specific(["Baz"])), + .sourceControl(path: "./bazzz", requirement: .exact("1.0.0"), products: .specific(["Baz"])) ] try await workspace.checkPackageGraphFailure(roots: ["Overridden/bazzz-master"], deps: deps) { diagnostics in @@ -5695,32 +5756,38 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "Bar", package: "bar"), - .product(name: "Baz", package: "baz"), - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "Bar", package: "bar"), + .product(name: "Baz", package: "baz"), + ] + ) ], products: [], dependencies: [ .sourceControl(url: "https://localhost/org/bar", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(url: "https://localhost/org/baz", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Bar", url: "https://localhost/org/bar", targets: [ - MockTarget(name: "Bar", dependencies: [ - .product(name: "Baz", package: "Baz"), - ]), + MockTarget( + name: "Bar", + dependencies: [ + .product(name: "Baz", package: "Baz") + ] + ) ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], dependencies: [ - .sourceControl(url: "https://localhost/org/Baz", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://localhost/org/Baz", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -5728,10 +5795,10 @@ final class WorkspaceTests: XCTestCase { name: "Baz", url: "https://localhost/org/baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0"] ), @@ -5739,10 +5806,10 @@ final class WorkspaceTests: XCTestCase { name: "Baz", url: "https://localhost/org/Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0"] ), @@ -5789,17 +5856,17 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar", settings: [.init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"]))]), + MockTarget(name: "Bar", settings: [.init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"]))]) ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", nil], ), MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar", "Baz"]), + MockTarget(name: "Foo", dependencies: ["Bar", "Baz"]) ], products: [], dependencies: [ @@ -5812,10 +5879,10 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar", settings: [.init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"]))]), + MockTarget(name: "Bar", settings: [.init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"]))]) ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["1.0.0", nil], ), @@ -5826,13 +5893,13 @@ final class WorkspaceTests: XCTestCase { name: "Baz", dependencies: ["Bar"], settings: [.init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"]))] - ), + ) ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0", "1.5.0"], toolsVersion: .minimumRequired @@ -5875,15 +5942,15 @@ final class WorkspaceTests: XCTestCase { .product( name: "Foundation", package: "swift-corelibs-foundation" - ), + ) ] - ), + ) ], products: [], dependencies: [ - .sourceControl(path: "swift-corelibs-foundation", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "swift-corelibs-foundation", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( @@ -5892,13 +5959,13 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "Foundation", settings: [.init(tool: .swift, kind: .unsafeFlags(["-F", "/tmp"]))] - ), + ) ], products: [ - MockProduct(name: "Foundation", modules: ["Foundation"]), + MockProduct(name: "Foundation", modules: ["Foundation"]) ], versions: ["1.0.0", nil] - ), + ) ] ) @@ -5918,49 +5985,49 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Root", dependencies: ["Foo", "Baz"]), + MockTarget(name: "Root", dependencies: ["Foo", "Baz"]) ], products: [], dependencies: [ .sourceControl(path: "./Foo", requirement: .branch("master")), .sourceControl(path: "./Baz", requirement: .upToNextMajor(from: "1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Foo", targets: [ - MockTarget(name: "Foo", dependencies: ["Bar"]), + MockTarget(name: "Foo", dependencies: ["Bar"]) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .branch("master")), + .sourceControl(path: "./Bar", requirement: .branch("master")) ], versions: ["master", nil] ), MockPackage( name: "Bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["master", "1.0.0", nil] ), MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz", dependencies: ["Bar"]), + MockTarget(name: "Baz", dependencies: ["Bar"]) ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], dependencies: [ - .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "./Bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0", nil] ), @@ -6014,14 +6081,14 @@ final class WorkspaceTests: XCTestCase { let barProducts: [MockProduct] #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - barProducts = [ - MockProduct(name: "Bar", modules: ["Bar"]), - MockProduct(name: "BarUnused", modules: ["BarUnused"]), - ] + barProducts = [ + MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "BarUnused", modules: ["BarUnused"]), + ] #else - // Whether a product is being used does not affect dependency resolution in this case, so we omit the unused - // product. - barProducts = [MockProduct(name: "Bar", modules: ["Bar"])] + // Whether a product is being used does not affect dependency resolution in this case, so we omit the unused + // product. + barProducts = [MockProduct(name: "Bar", modules: ["Bar"])] #endif let workspace = try await MockWorkspace( @@ -6041,7 +6108,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./TestHelper1", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_2 - ), + ) ], packages: [ MockPackage( @@ -6052,7 +6119,7 @@ final class WorkspaceTests: XCTestCase { MockTarget(name: "FooTests", dependencies: ["TestHelper2"], type: .test), ], products: [ - MockProduct(name: "Foo", modules: ["Foo1"]), + MockProduct(name: "Foo", modules: ["Foo1"]) ], dependencies: [ .sourceControl(path: "./TestHelper2", requirement: .upToNextMajor(from: "1.0.0")), @@ -6079,10 +6146,10 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0"], toolsVersion: .v5_2 @@ -6090,10 +6157,10 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "TestHelper1", targets: [ - MockTarget(name: "TestHelper1"), + MockTarget(name: "TestHelper1") ], products: [ - MockProduct(name: "TestHelper1", modules: ["TestHelper1"]), + MockProduct(name: "TestHelper1", modules: ["TestHelper1"]) ], versions: ["1.0.0"], toolsVersion: .v5_2 @@ -6148,18 +6215,21 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "A1", package: "A"), - .product(name: "A2", package: "A"), - .product(name: "B", package: "B"), - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "A1", package: "A"), + .product(name: "A2", package: "A"), + .product(name: "B", package: "B"), + ] + ) ], products: [], dependencies: [ .sourceControl(path: "./A", requirement: .exact("1.0.0")), .sourceControl(path: "./B", requirement: .exact("1.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -6189,10 +6259,10 @@ final class WorkspaceTests: XCTestCase { name: "B", type: .binary, path: "XCFrameworks/B.zip" - ), + ) ], products: [ - MockProduct(name: "B", modules: ["B"]), + MockProduct(name: "B", modules: ["B"]) ], versions: ["1.0.0"] ), @@ -6239,11 +6309,14 @@ final class WorkspaceTests: XCTestCase { XCTAssertTrue(fs.exists(bFrameworkArchivePath)) // Ensure that the temporary folders have been properly created - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"]), - sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), - sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), - ]) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), + sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), + ] + ) // Ensure that the temporary directories have been removed XCTAssertTrue(try! fs.getDirectoryContents(sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"])).isEmpty) @@ -6359,18 +6432,21 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "A1", package: "A"), - .product(name: "A2", package: "A"), - .product(name: "A3", package: "A"), - .product(name: "A4", package: "A"), - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "A1", package: "A"), + .product(name: "A2", package: "A"), + .product(name: "A3", package: "A"), + .product(name: "A4", package: "A"), + ] + ) ], products: [], dependencies: [ - .sourceControl(path: "./A", requirement: .exact("1.0.0")), + .sourceControl(path: "./A", requirement: .exact("1.0.0")) ] - ), + ) ], packages: [ MockPackage( @@ -6405,7 +6481,7 @@ final class WorkspaceTests: XCTestCase { MockProduct(name: "A4", modules: ["A4"]), ], versions: ["1.0.0"] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -6593,9 +6669,9 @@ final class WorkspaceTests: XCTestCase { name: "A1", type: .binary, path: "XCFrameworks/archived-does-not-match-target-name.zip" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( archiver: archiver @@ -6642,7 +6718,7 @@ final class WorkspaceTests: XCTestCase { path: "ArtifactBundles/A2.zip" ), ] - ), + ) ], binaryArtifactsManager: .init( archiver: archiver @@ -6705,7 +6781,7 @@ final class WorkspaceTests: XCTestCase { path: "ArtifactBundles/A2.zip" ), ] - ), + ) ], binaryArtifactsManager: .init( archiver: archiver @@ -6742,7 +6818,7 @@ final class WorkspaceTests: XCTestCase { } } -////// STAET ATDIN + ////// STAET ATDIN func testLocalArchivedArtifactChecksumChange() async throws { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -6784,7 +6860,7 @@ final class WorkspaceTests: XCTestCase { path: "XCFrameworks/A2.zip" ), ] - ), + ) ], binaryArtifactsManager: .init( archiver: archiver @@ -6826,9 +6902,12 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, _ in // Ensure that only the artifact archive with the changed checksum has been extracted - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), - ]) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]) + ] + ) } await workspace.checkManagedArtifacts { result in @@ -6869,7 +6948,7 @@ final class WorkspaceTests: XCTestCase { .writeFileContents( nestedPath.appending(".DS_Store"), bytes: [] - ) // add a file next to the directory + ) // add a file next to the directory default: throw StringError("unexpected archivePath \(archivePath)") } @@ -6905,7 +6984,7 @@ final class WorkspaceTests: XCTestCase { path: "frameworks/nested2.zip" ), ] - ), + ) ], binaryArtifactsManager: .init( archiver: archiver @@ -6928,11 +7007,14 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root"]))) - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "root", "flat"]), - sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested"]), - sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested2"]), - ]) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "root", "flat"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested2"]), + ] + ) } await workspace.checkManagedArtifacts { result in @@ -6979,7 +7061,7 @@ final class WorkspaceTests: XCTestCase { path: "ArtifactBundles/A2.artifactbundle" ), ] - ), + ) ] ) @@ -7031,7 +7113,7 @@ final class WorkspaceTests: XCTestCase { path: "ArtifactBundles/incorrect.artifactbundle" ), ] - ), + ) ] ) @@ -7114,18 +7196,21 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "A1", package: "A"), - .product(name: "A2", package: "A"), - "B", - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "A1", package: "A"), + .product(name: "A2", package: "A"), + "B", + ] + ) ], products: [], dependencies: [ .sourceControl(path: "./A", requirement: .exact("1.0.0")), .sourceControl(path: "./B", requirement: .exact("1.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -7158,10 +7243,10 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://b.com/b.zip", checksum: "b0" - ), + ) ], products: [ - MockProduct(name: "B", modules: ["B"]), + MockProduct(name: "B", modules: ["B"]) ], versions: ["1.0.0"] ), @@ -7169,7 +7254,7 @@ final class WorkspaceTests: XCTestCase { binaryArtifactsManager: .init( httpClient: httpClient, archiver: archiver, - useCache: false // disable cache + useCache: false // disable cache ) ) @@ -7177,21 +7262,30 @@ final class WorkspaceTests: XCTestCase { XCTAssertNoDiagnostics(diagnostics) XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "a"]))) XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "b"]))) - XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ - "https://a.com/a1.zip", - "https://a.com/a2.zip", - "https://b.com/b.zip", - ]) - XCTAssertEqual(workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), [ - ByteString([0xA1]).hexadecimalRepresentation, - ByteString([0xA2]).hexadecimalRepresentation, - ByteString([0xB0]).hexadecimalRepresentation, - ]) - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"]), - sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), - sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), - ]) + XCTAssertEqual( + downloads.map(\.key.absoluteString).sorted(), + [ + "https://a.com/a1.zip", + "https://a.com/a2.zip", + "https://b.com/b.zip", + ] + ) + XCTAssertEqual( + workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), + [ + ByteString([0xA1]).hexadecimalRepresentation, + ByteString([0xA2]).hexadecimalRepresentation, + ByteString([0xB0]).hexadecimalRepresentation, + ] + ) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), + sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), + ] + ) XCTAssertEqual( downloads.map(\.value).sorted(), archiver.extractions.map(\.archivePath).sorted() @@ -7288,7 +7382,7 @@ final class WorkspaceTests: XCTestCase { case "a2.zip": try createDummyXCFramework(fileSystem: fs, path: destinationPath, name: "A2") case "a3.zip": - fs.createEmptyFiles(at: destinationPath, files: ".DS_Store") // invalid binary artifact + fs.createEmptyFiles(at: destinationPath, files: ".DS_Store") // invalid binary artifact case "a7.zip": try createDummyXCFramework(fileSystem: fs, path: destinationPath, name: "A7") case "b.zip": @@ -7311,21 +7405,24 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - "B", - .product(name: "A1", package: "A"), - .product(name: "A2", package: "A"), - .product(name: "A3", package: "A"), - .product(name: "A4", package: "A"), - .product(name: "A7", package: "A"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + "B", + .product(name: "A1", package: "A"), + .product(name: "A2", package: "A"), + .product(name: "A3", package: "A"), + .product(name: "A4", package: "A"), + .product(name: "A7", package: "A"), + ] + ) ], products: [], dependencies: [ .sourceControl(path: "./A", requirement: .exact("1.0.0")), .sourceControl(path: "./B", requirement: .exact("1.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -7378,10 +7475,10 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://b.com/b.zip", checksum: "b0" - ), + ) ], products: [ - MockProduct(name: "B", modules: ["B"]), + MockProduct(name: "B", modules: ["B"]) ], versions: ["1.0.0"] ), @@ -7478,24 +7575,33 @@ final class WorkspaceTests: XCTestCase { XCTAssert(!fs.exists(sandbox.appending(components: [".build", "artifacts", "a", "A5", "A5.xcframework"]))) XCTAssert(fs.exists(sandbox.appending(components: ["pkgs", "a", "XCFrameworks", "A7.xcframework"]))) XCTAssert(!fs.exists(sandbox.appending(components: [".build", "artifacts", "Foo"]))) - XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ - "https://a.com/a2.zip", - "https://a.com/a3.zip", - "https://a.com/a7.zip", - "https://b.com/b.zip", - ]) - XCTAssertEqual(workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), [ - ByteString([0xA2]).hexadecimalRepresentation, - ByteString([0xA3]).hexadecimalRepresentation, - ByteString([0xA7]).hexadecimalRepresentation, - ByteString([0xB0]).hexadecimalRepresentation, - ]) - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract","a", "A2"]), - sandbox.appending(components: [".build", "artifacts", "extract","a", "A3"]), - sandbox.appending(components: [".build", "artifacts", "extract","a", "A7"]), - sandbox.appending(components: [".build", "artifacts", "extract","b", "B"]), - ]) + XCTAssertEqual( + downloads.map(\.key.absoluteString).sorted(), + [ + "https://a.com/a2.zip", + "https://a.com/a3.zip", + "https://a.com/a7.zip", + "https://b.com/b.zip", + ] + ) + XCTAssertEqual( + workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), + [ + ByteString([0xA2]).hexadecimalRepresentation, + ByteString([0xA3]).hexadecimalRepresentation, + ByteString([0xA7]).hexadecimalRepresentation, + ByteString([0xB0]).hexadecimalRepresentation, + ] + ) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A3"]), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A7"]), + sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), + ] + ) XCTAssertEqual( downloads.map(\.value).sorted(), archiver.extractions.map(\.archivePath).sorted() @@ -7614,9 +7720,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a1.zip", checksum: "a1" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -7628,22 +7734,31 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root"]))) - XCTAssertEqual(workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), [ - ByteString([0xA1]).hexadecimalRepresentation, - ]) + XCTAssertEqual( + workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), + [ + ByteString([0xA1]).hexadecimalRepresentation + ] + ) } - XCTAssertEqual(downloads.map(\.0.absoluteString).sorted(), [ - "https://a.com/a1.zip", - ]) - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), - ]) XCTAssertEqual( - downloads.map(\.1).sorted(), - archiver.extractions.map(\.archivePath).sorted() + downloads.map(\.0.absoluteString).sorted(), + [ + "https://a.com/a1.zip" + ] ) - + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]) + ] + ) + XCTAssertEqual( + downloads.map(\.1).sorted(), + archiver.extractions.map(\.archivePath).sorted() + ) + // reset try await workspace.resetState() @@ -7654,18 +7769,27 @@ final class WorkspaceTests: XCTestCase { XCTAssertNoDiagnostics(diagnostics) XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root"]))) - XCTAssertEqual(workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), [ - ByteString([0xA1]).hexadecimalRepresentation, ByteString([0xA1]).hexadecimalRepresentation, - ]) + XCTAssertEqual( + workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), + [ + ByteString([0xA1]).hexadecimalRepresentation, ByteString([0xA1]).hexadecimalRepresentation, + ] + ) } - XCTAssertEqual(downloads.map(\.0.absoluteString).sorted(), [ - "https://a.com/a1.zip", "https://a.com/a1.zip", - ]) - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), - sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), - ]) + XCTAssertEqual( + downloads.map(\.0.absoluteString).sorted(), + [ + "https://a.com/a1.zip", "https://a.com/a1.zip", + ] + ) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), + ] + ) XCTAssertEqual( downloads.map(\.1).sorted(), archiver.extractions.map(\.archivePath).sorted() @@ -7705,9 +7829,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: artifactUrl, checksum: "a1" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient @@ -7731,9 +7855,10 @@ final class WorkspaceTests: XCTestCase { // make sure the cached artifact is also deleted let artifactCacheKey = artifactUrl.spm_mangledToC99ExtendedIdentifier() - guard let cachePath = workspace.workspaceLocation? - .sharedBinaryArtifactsCacheDirectory? - .appending(artifactCacheKey) + guard + let cachePath = workspace.workspaceLocation? + .sharedBinaryArtifactsCacheDirectory? + .appending(artifactCacheKey) else { XCTFail("Required workspace location wasn't found") return @@ -7797,7 +7922,7 @@ final class WorkspaceTests: XCTestCase { checksum: "a3" ), ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -7911,7 +8036,7 @@ final class WorkspaceTests: XCTestCase { ], products: [], dependencies: [] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -7984,11 +8109,11 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a1.zip", checksum: "a1" - ), + ) ], products: [], dependencies: [] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -8054,11 +8179,11 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/foo.zip", checksum: "a1" - ), + ) ], products: [], dependencies: [] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -8084,9 +8209,11 @@ final class WorkspaceTests: XCTestCase { } func testArtifactChecksum() async throws { - try XCTSkipOnWindows(because: #""" - threw error "\tmp\ws doesn't exist in file system" because there is an issue with InMemoryFileSystem readFileContents(...) on Windows - """#) + try XCTSkipOnWindows( + because: #""" + threw error "\tmp\ws doesn't exist in file system" because there is an issue with InMemoryFileSystem readFileContents(...) on Windows + """# + ) let fs = InMemoryFileSystem() try fs.createMockToolchain() @@ -8175,9 +8302,9 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "A", type: .binary, url: "https://a.com/a.zip", checksum: "new-checksum"), + MockTarget(name: "A", type: .binary, url: "https://a.com/a.zip", checksum: "new-checksum") ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient @@ -8198,7 +8325,7 @@ final class WorkspaceTests: XCTestCase { ), path: workspace.artifactsDir.appending(components: "Root", "A.xcframework"), kind: .xcframework - ), + ) ] ) @@ -8270,9 +8397,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/b.zip", checksum: "b1" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -8294,7 +8421,7 @@ final class WorkspaceTests: XCTestCase { ), path: workspace.artifactsDir.appending(components: "Root", "A.xcframework"), kind: .xcframework - ), + ) ] ) @@ -8361,9 +8488,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a1.zip", checksum: "a1" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -8373,9 +8500,12 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) - XCTAssertEqual(acceptHeaders.get(), [ - "application/octet-stream", - ]) + XCTAssertEqual( + acceptHeaders.get(), + [ + "application/octet-stream" + ] + ) } } @@ -8437,9 +8567,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a1.zip", checksum: "a1" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -8526,9 +8656,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a1.zip", checksum: "a1" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -8633,39 +8763,45 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "A", package: "A"), - .product(name: "B", package: "B"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "A", package: "A"), + .product(name: "B", package: "B"), + ] + ) ], products: [], dependencies: [ .sourceControl(path: "./A", requirement: .exact("1.0.0")), .sourceControl(path: "./B", requirement: .exact("1.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "A", targets: [ - MockTarget(name: "A", type: .binary, url: "https://a.com/a.zip", checksum: "0a"), + MockTarget(name: "A", type: .binary, url: "https://a.com/a.zip", checksum: "0a") ], products: [ - MockProduct(name: "A", modules: ["A"]), + MockProduct(name: "A", modules: ["A"]) ], versions: ["1.0.0"] ), MockPackage( name: "B", targets: [ - MockTarget(name: "B", dependencies: [ - .product(name: "C", package: "C"), - .product(name: "D", package: "D"), - ]), + MockTarget( + name: "B", + dependencies: [ + .product(name: "C", package: "C"), + .product(name: "D", package: "D"), + ] + ) ], products: [ - MockProduct(name: "B", modules: ["B"]), + MockProduct(name: "B", modules: ["B"]) ], dependencies: [ .sourceControl(path: "./C", requirement: .exact("1.0.0")), @@ -8676,30 +8812,36 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "C", targets: [ - MockTarget(name: "C", dependencies: [ - .product(name: "A", package: "A"), - ]), + MockTarget( + name: "C", + dependencies: [ + .product(name: "A", package: "A") + ] + ) ], products: [ - MockProduct(name: "C", modules: ["C"]), + MockProduct(name: "C", modules: ["C"]) ], dependencies: [ - .sourceControl(path: "./A", requirement: .exact("1.0.0")), + .sourceControl(path: "./A", requirement: .exact("1.0.0")) ], versions: ["1.0.0"] ), MockPackage( name: "D", targets: [ - MockTarget(name: "D", dependencies: [ - .product(name: "A", package: "A"), - ]), + MockTarget( + name: "D", + dependencies: [ + .product(name: "A", package: "A") + ] + ) ], products: [ - MockProduct(name: "D", modules: ["D"]), + MockProduct(name: "D", modules: ["D"]) ], dependencies: [ - .sourceControl(path: "./A", requirement: .exact("1.0.0")), + .sourceControl(path: "./A", requirement: .exact("1.0.0")) ], versions: ["1.0.0"] ), @@ -8714,15 +8856,24 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "a"]))) - XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ - "https://a.com/a.zip", - ]) - XCTAssertEqual(workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), [ - ByteString([0xA]).hexadecimalRepresentation, - ]) - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "a", "A"]), - ]) + XCTAssertEqual( + downloads.map(\.key.absoluteString).sorted(), + [ + "https://a.com/a.zip" + ] + ) + XCTAssertEqual( + workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), + [ + ByteString([0xA]).hexadecimalRepresentation + ] + ) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A"]) + ] + ) XCTAssertEqual( downloads.map(\.value).sorted(), archiver.extractions.map(\.archivePath).sorted() @@ -8817,9 +8968,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/binary.zip", checksum: "01" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -8897,7 +9048,7 @@ final class WorkspaceTests: XCTestCase { } }) - let packages = try (0 ... maxConcurrentRequests * 10).map { index in + let packages = try (0...maxConcurrentRequests * 10).map { index in try MockPackage( name: "library\(index)", targets: [ @@ -8906,10 +9057,10 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://somewhere.com/binary\(index).zip", checksum: "01" - ), + ) ], products: [ - MockProduct(name: "binary\(index)", modules: ["binary\(index)"]), + MockProduct(name: "binary\(index)", modules: ["binary\(index)"]) ], versions: ["1.0.0"] ) @@ -8927,13 +9078,13 @@ final class WorkspaceTests: XCTestCase { dependencies: packages.map { package in .product(name: package.targets.first!.name, package: package.name) } - ), + ) ], products: [], dependencies: packages.map { package in .sourceControl(path: "./\(package.name)", requirement: .exact("1.0.0")) } - ), + ) ], packages: packages, binaryArtifactsManager: .init( @@ -9021,7 +9172,7 @@ final class WorkspaceTests: XCTestCase { .writeFileContents( nestedPath.appending(".DS_Store"), bytes: [] - ) // add a file next to the directory + ) // add a file next to the directory archiver.extractions .append(MockArchiver.Extraction(archivePath: archivePath, destinationPath: destinationPath)) @@ -9062,7 +9213,7 @@ final class WorkspaceTests: XCTestCase { checksum: "03" ), ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -9074,21 +9225,30 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root"]))) - XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ - "https://a.com/flat.zip", - "https://a.com/nested.zip", - "https://a.com/nested2.zip", - ]) - XCTAssertEqual(workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), [ - ByteString([0x01]).hexadecimalRepresentation, - ByteString([0x02]).hexadecimalRepresentation, - ByteString([0x03]).hexadecimalRepresentation, - ]) - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "root", "flat"]), - sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested"]), - sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested2"]), - ]) + XCTAssertEqual( + downloads.map(\.key.absoluteString).sorted(), + [ + "https://a.com/flat.zip", + "https://a.com/nested.zip", + "https://a.com/nested2.zip", + ] + ) + XCTAssertEqual( + workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), + [ + ByteString([0x01]).hexadecimalRepresentation, + ByteString([0x02]).hexadecimalRepresentation, + ByteString([0x03]).hexadecimalRepresentation, + ] + ) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "root", "flat"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested2"]), + ] + ) XCTAssertEqual( downloads.map(\.value).sorted(), archiver.extractions.map(\.archivePath).sorted() @@ -9199,7 +9359,7 @@ final class WorkspaceTests: XCTestCase { ), ], products: [] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -9210,18 +9370,27 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) - XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ - "https://a.com/a1.xcframework.zip", - "https://a.com/a2.zip.zip", - ]) - XCTAssertEqual(workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), [ - ByteString([0xA1]).hexadecimalRepresentation, - ByteString([0xA2]).hexadecimalRepresentation, - ]) - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), - sandbox.appending(components: [".build", "artifacts", "extract", "root", "A2"]), - ]) + XCTAssertEqual( + downloads.map(\.key.absoluteString).sorted(), + [ + "https://a.com/a1.xcframework.zip", + "https://a.com/a2.zip.zip", + ] + ) + XCTAssertEqual( + workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), + [ + ByteString([0xA1]).hexadecimalRepresentation, + ByteString([0xA2]).hexadecimalRepresentation, + ] + ) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A2"]), + ] + ) XCTAssertEqual( downloads.map(\.value).sorted(), archiver.extractions.map(\.archivePath).sorted() @@ -9286,7 +9455,7 @@ final class WorkspaceTests: XCTestCase { ), ], products: [] - ), + ) ] ) @@ -9333,7 +9502,7 @@ final class WorkspaceTests: XCTestCase { """, ] - let checksumAlgorithm = MockHashAlgorithm() // used in tests + let checksumAlgorithm = MockHashAlgorithm() // used in tests let ariFilesChecksums = ariFiles.map { checksumAlgorithm.hash($0).hexadecimalRepresentation } // returns a dummy file for the requested artifact @@ -9405,18 +9574,21 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "Foo", dependencies: [ - .product(name: "A1", package: "A"), - .product(name: "A2", package: "A"), - "B", - ]), + MockTarget( + name: "Foo", + dependencies: [ + .product(name: "A1", package: "A"), + .product(name: "A2", package: "A"), + "B", + ] + ) ], products: [], dependencies: [ .sourceControl(path: "./A", requirement: .exact("1.0.0")), .sourceControl(path: "./B", requirement: .exact("1.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -9449,10 +9621,10 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://b.com/b.zip", checksum: "b0" - ), + ) ], products: [ - MockProduct(name: "B", modules: ["B"]), + MockProduct(name: "B", modules: ["B"]) ], versions: ["1.0.0"] ), @@ -9469,28 +9641,30 @@ final class WorkspaceTests: XCTestCase { XCTAssertNoDiagnostics(diagnostics) XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "a"]))) XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "b"]))) - XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ - "https://a.com/a1.zip", - "https://a.com/a2/a2.zip", - "https://b.com/b.zip", - ]) + XCTAssertEqual( + downloads.map(\.key.absoluteString).sorted(), + [ + "https://a.com/a1.zip", + "https://a.com/a2/a2.zip", + "https://b.com/b.zip", + ] + ) XCTAssertEqual( checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), - ( - ariFiles.map(ByteString.init(encodingAsUTF8:)) + - ariFiles.map(ByteString.init(encodingAsUTF8:)) + - [ - ByteString([0xA1]), - ByteString([0xA2]), - ByteString([0xB0]), - ] - ).map(\.hexadecimalRepresentation).sorted() + (ariFiles.map(ByteString.init(encodingAsUTF8:)) + ariFiles.map(ByteString.init(encodingAsUTF8:)) + [ + ByteString([0xA1]), + ByteString([0xA2]), + ByteString([0xB0]), + ]).map(\.hexadecimalRepresentation).sorted() + ) + XCTAssertEqual( + archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), + [ + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), + sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), + ] ) - XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"]), - sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), - sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), - ]) XCTAssertEqual( downloads.map(\.value).sorted(), archiver.extractions.map(\.archivePath).sorted() @@ -9562,9 +9736,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a.artifactbundleindex", checksum: "does-not-matter" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient @@ -9590,18 +9764,18 @@ final class WorkspaceTests: XCTestCase { let hostToolchain = try UserToolchain.mockHostToolchain(fs) let ari = """ - { - "schemaVersion": "1.0", - "archives": [ - { - "fileName": "a1.zip", - "checksum": "a1", - "supportedTriples": ["\(hostToolchain.targetTriple.tripleString)"] - } - ] - } - """ - let checksumAlgorithm = MockHashAlgorithm() // used in tests + { + "schemaVersion": "1.0", + "archives": [ + { + "fileName": "a1.zip", + "checksum": "a1", + "supportedTriples": ["\(hostToolchain.targetTriple.tripleString)"] + } + ] + } + """ + let checksumAlgorithm = MockHashAlgorithm() // used in tests let ariChecksums = checksumAlgorithm.hash(ari).hexadecimalRepresentation // returns a dummy files for the requested artifact @@ -9628,9 +9802,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a.artifactbundleindex", checksum: "incorrect" - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient @@ -9665,9 +9839,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a.artifactbundleindex", checksum: "new-checksum" - ), + ) ] - ), + ) ] ) @@ -9685,7 +9859,7 @@ final class WorkspaceTests: XCTestCase { ), path: workspace.artifactsDir.appending(components: "root", "A.xcframework"), kind: .xcframework - ), + ) ] ) @@ -9706,18 +9880,18 @@ final class WorkspaceTests: XCTestCase { let hostToolchain = try UserToolchain.mockHostToolchain(fs) let ari = """ - { - "schemaVersion": "1.0", - "archives": [ - { - "fileName": "a.zip", - "checksum": "a", - "supportedTriples": ["\(hostToolchain.targetTriple.tripleString)"] - } - ] - } - """ - let checksumAlgorithm = MockHashAlgorithm() // used in tests + { + "schemaVersion": "1.0", + "archives": [ + { + "fileName": "a.zip", + "checksum": "a", + "supportedTriples": ["\(hostToolchain.targetTriple.tripleString)"] + } + ] + } + """ + let checksumAlgorithm = MockHashAlgorithm() // used in tests let ariChecksums = checksumAlgorithm.hash(ari).hexadecimalRepresentation // returns a dummy files for the requested artifact @@ -9784,9 +9958,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a.artifactbundleindex", checksum: ariChecksums - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient, @@ -9813,18 +9987,18 @@ final class WorkspaceTests: XCTestCase { let hostToolchain = try UserToolchain.mockHostToolchain(fs) let ari = """ - { - "schemaVersion": "1.0", - "archives": [ - { - "fileName": "not-found.zip", - "checksum": "a", - "supportedTriples": ["\(hostToolchain.targetTriple.tripleString)"] - } - ] - } - """ - let checksumAlgorithm = MockHashAlgorithm() // used in tests + { + "schemaVersion": "1.0", + "archives": [ + { + "fileName": "not-found.zip", + "checksum": "a", + "supportedTriples": ["\(hostToolchain.targetTriple.tripleString)"] + } + ] + } + """ + let checksumAlgorithm = MockHashAlgorithm() // used in tests let ariChecksums = checksumAlgorithm.hash(ari).hexadecimalRepresentation // returns a dummy files for the requested artifact @@ -9857,9 +10031,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a.artifactbundleindex", checksum: ariChecksums - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient @@ -9890,18 +10064,18 @@ final class WorkspaceTests: XCTestCase { let notHostTriple = hostToolchain.targetTriple == androidTriple ? macTriple : androidTriple let ari = """ - { - "schemaVersion": "1.0", - "archives": [ - { - "fileName": "a1.zip", - "checksum": "a1", - "supportedTriples": ["\(notHostTriple.tripleString)"] - } - ] - } - """ - let checksumAlgorithm = MockHashAlgorithm() // used in tests + { + "schemaVersion": "1.0", + "archives": [ + { + "fileName": "a1.zip", + "checksum": "a1", + "supportedTriples": ["\(notHostTriple.tripleString)"] + } + ] + } + """ + let checksumAlgorithm = MockHashAlgorithm() // used in tests let ariChecksum = checksumAlgorithm.hash(ari).hexadecimalRepresentation // returns a dummy files for the requested artifact @@ -9928,9 +10102,9 @@ final class WorkspaceTests: XCTestCase { type: .binary, url: "https://a.com/a.artifactbundleindex", checksum: ariChecksum - ), + ) ] - ), + ) ], binaryArtifactsManager: .init( httpClient: httpClient @@ -9960,10 +10134,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "FooUtilityPackage"), - .product(name: "BarProduct", package: "BarUtilityPackage"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "FooUtilityPackage"), + .product(name: "BarProduct", package: "BarUtilityPackage"), + ] + ) ], products: [], dependencies: [ @@ -9979,17 +10156,17 @@ final class WorkspaceTests: XCTestCase { ), ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "FooUtilityPackage", path: "foo/utility", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -9998,10 +10175,10 @@ final class WorkspaceTests: XCTestCase { name: "BarUtilityPackage", path: "bar/utility", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10029,10 +10206,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "FooUtilityPackage"), - .product(name: "BarProduct", package: "BarUtilityPackage"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "FooUtilityPackage"), + .product(name: "BarProduct", package: "BarUtilityPackage"), + ] + ) ], products: [], dependencies: [ @@ -10040,17 +10220,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar/utility", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "FooUtilityPackage", path: "foo/utility", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10059,10 +10239,10 @@ final class WorkspaceTests: XCTestCase { name: "BarUtilityPackage", path: "bar/utility", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10091,10 +10271,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "FooPackage"), - .product(name: "BarProduct", package: "BarPackage"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "FooPackage"), + .product(name: "BarProduct", package: "BarPackage"), + ] + ) ], products: [], dependencies: [ @@ -10110,17 +10293,17 @@ final class WorkspaceTests: XCTestCase { ), ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "FooPackage", path: "foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10129,10 +10312,10 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10160,28 +10343,31 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - "FooProduct", - "BarProduct", - ]), - ], - products: [], - dependencies: [ + MockTarget( + name: "RootTarget", + dependencies: [ + "FooProduct", + "BarProduct", + ] + ) + ], + products: [], + dependencies: [ .sourceControl(path: "foo", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "MyPackage", path: "foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10189,10 +10375,10 @@ final class WorkspaceTests: XCTestCase { name: "MyPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10215,10 +10401,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -10226,17 +10415,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "MyPackage", path: "foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10244,10 +10433,10 @@ final class WorkspaceTests: XCTestCase { name: "MyPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10270,10 +10459,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - "FooProduct", - "BarProduct", - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + "FooProduct", + "BarProduct", + ] + ) ], products: [], dependencies: [ @@ -10281,17 +10473,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "foo", path: "foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10299,10 +10491,10 @@ final class WorkspaceTests: XCTestCase { name: "foo", path: "bar", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10325,10 +10517,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - "FooProduct", - "BarProduct", - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + "FooProduct", + "BarProduct", + ] + ) ], products: [], dependencies: [ @@ -10336,17 +10531,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_3 - ), + ) ], packages: [ MockPackage( name: "foo", path: "foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10354,10 +10549,10 @@ final class WorkspaceTests: XCTestCase { name: "foo", path: "bar", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10389,10 +10584,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -10400,17 +10598,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_3 - ), + ) ], packages: [ MockPackage( name: "foo", path: "foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10418,10 +10616,10 @@ final class WorkspaceTests: XCTestCase { name: "foo", path: "bar", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10444,10 +10642,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - "FooProduct", - "BarProduct", - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + "FooProduct", + "BarProduct", + ] + ) ], products: [], dependencies: [ @@ -10459,17 +10660,17 @@ final class WorkspaceTests: XCTestCase { ), ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "foo", path: "foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10477,10 +10678,10 @@ final class WorkspaceTests: XCTestCase { name: "foo", path: "bar", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10508,10 +10709,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "foo"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "foo"), + ] + ) ], products: [], dependencies: [ @@ -10523,17 +10727,17 @@ final class WorkspaceTests: XCTestCase { ), ], toolsVersion: .v5_3 - ), + ) ], packages: [ MockPackage( name: "foo", path: "foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10541,10 +10745,10 @@ final class WorkspaceTests: XCTestCase { name: "foo", path: "bar", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -10572,10 +10776,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooUtilityProduct", package: "FooUtilityPackage"), - .product(name: "BarProduct", package: "BarPackage"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooUtilityProduct", package: "FooUtilityPackage"), + .product(name: "BarProduct", package: "BarPackage"), + ] + ) ], products: [], dependencies: [ @@ -10591,17 +10798,17 @@ final class WorkspaceTests: XCTestCase { ), ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "FooUtilityPackage", path: "foo/utility", targets: [ - MockTarget(name: "FooUtilityTarget"), + MockTarget(name: "FooUtilityTarget") ], products: [ - MockProduct(name: "FooUtilityProduct", modules: ["FooUtilityTarget"]), + MockProduct(name: "FooUtilityProduct", modules: ["FooUtilityTarget"]) ], versions: ["1.0.0"] ), @@ -10609,19 +10816,22 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "OtherUtilityProduct", package: "OtherUtilityPackage"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "OtherUtilityProduct", package: "OtherUtilityPackage") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControlWithDeprecatedName( name: "OtherUtilityPackage", path: "other/utility", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -10630,10 +10840,10 @@ final class WorkspaceTests: XCTestCase { name: "OtherUtilityPackage", path: "other/utility", targets: [ - MockTarget(name: "OtherUtilityTarget"), + MockTarget(name: "OtherUtilityTarget") ], products: [ - MockProduct(name: "OtherUtilityProduct", modules: ["OtherUtilityTarget"]), + MockProduct(name: "OtherUtilityProduct", modules: ["OtherUtilityTarget"]) ], versions: ["1.0.0"] ), @@ -10662,10 +10872,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "HouseProduct", package: "HousePackage"), - .product(name: "ShackProduct", package: "ShackPackage"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "HouseProduct", package: "HousePackage"), + .product(name: "ShackProduct", package: "ShackPackage"), + ] + ) ], products: [], dependencies: [ @@ -10680,20 +10893,23 @@ final class WorkspaceTests: XCTestCase { requirement: .upToNextMajor(from: "1.0.0") ), ] - ), + ) ], packages: [ MockPackage( name: "HousePackage", path: "house", targets: [ - MockTarget(name: "HouseTarget", dependencies: [ - .product(name: "BudgetWindowProduct", package: "BudgetWindowPackage"), - .product(name: "PremiumWindowProduct", package: "PremiumWindowPackage"), - ]), + MockTarget( + name: "HouseTarget", + dependencies: [ + .product(name: "BudgetWindowProduct", package: "BudgetWindowPackage"), + .product(name: "PremiumWindowProduct", package: "PremiumWindowPackage"), + ] + ) ], products: [ - MockProduct(name: "HouseProduct", modules: ["HouseTarget"]), + MockProduct(name: "HouseProduct", modules: ["HouseTarget"]) ], dependencies: [ .sourceControlWithDeprecatedName( @@ -10713,19 +10929,22 @@ final class WorkspaceTests: XCTestCase { name: "ShackPackage", path: "shack", targets: [ - MockTarget(name: "ShackTarget", dependencies: [ - .product(name: "StandardGlassProduct", package: "StandardGlassPackage"), - ]), + MockTarget( + name: "ShackTarget", + dependencies: [ + .product(name: "StandardGlassProduct", package: "StandardGlassPackage") + ] + ) ], products: [ - MockProduct(name: "ShackProduct", modules: ["ShackTarget"]), + MockProduct(name: "ShackProduct", modules: ["ShackTarget"]) ], dependencies: [ .sourceControlWithDeprecatedName( name: "StandardGlassPackage", path: "standard/glass", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -10733,19 +10952,22 @@ final class WorkspaceTests: XCTestCase { name: "BudgetWindowPackage", path: "budget_window", targets: [ - MockTarget(name: "BudgetWindowTarget", dependencies: [ - .product(name: "StandardGlassProduct", package: "StandardGlassPackage"), - ]), + MockTarget( + name: "BudgetWindowTarget", + dependencies: [ + .product(name: "StandardGlassProduct", package: "StandardGlassPackage") + ] + ) ], products: [ - MockProduct(name: "BudgetWindowProduct", modules: ["BudgetWindowTarget"]), + MockProduct(name: "BudgetWindowProduct", modules: ["BudgetWindowTarget"]) ], dependencies: [ .sourceControlWithDeprecatedName( name: "StandardGlassPackage", path: "standard/glass", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -10753,19 +10975,22 @@ final class WorkspaceTests: XCTestCase { name: "PremiumWindowPackage", path: "premium_window", targets: [ - MockTarget(name: "PremiumWindowTarget", dependencies: [ - .product(name: "TemperedGlassProduct", package: "TemperedGlassPackage"), - ]), + MockTarget( + name: "PremiumWindowTarget", + dependencies: [ + .product(name: "TemperedGlassProduct", package: "TemperedGlassPackage") + ] + ) ], products: [ - MockProduct(name: "PremiumWindowProduct", modules: ["PremiumWindowTarget"]), + MockProduct(name: "PremiumWindowProduct", modules: ["PremiumWindowTarget"]) ], dependencies: [ .sourceControlWithDeprecatedName( name: "TemperedGlassPackage", path: "tempered/glass", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -10773,10 +10998,10 @@ final class WorkspaceTests: XCTestCase { name: "StandardGlassPackage", path: "standard/glass", targets: [ - MockTarget(name: "StandardGlassTarget"), + MockTarget(name: "StandardGlassTarget") ], products: [ - MockProduct(name: "StandardGlassProduct", modules: ["StandardGlassTarget"]), + MockProduct(name: "StandardGlassProduct", modules: ["StandardGlassTarget"]) ], versions: ["1.0.0"] ), @@ -10786,10 +11011,10 @@ final class WorkspaceTests: XCTestCase { name: "TemperedGlassPackage", path: "tempered/glass", targets: [ - MockTarget(name: "TemperedTarget"), + MockTarget(name: "TemperedTarget") ], products: [ - MockProduct(name: "TemperedGlassProduct", modules: ["TemperedGlassTarget"]), + MockProduct(name: "TemperedGlassProduct", modules: ["TemperedGlassTarget"]) ], versions: ["1.0.0"] ), @@ -10833,9 +11058,12 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "River", targets: [ - MockTarget(name: "RiverTarget", dependencies: [ - .product(name: "FlowingWaterProduct", package: "FlowingWaterPackage"), - ]), + MockTarget( + name: "RiverTarget", + dependencies: [ + .product(name: "FlowingWaterProduct", package: "FlowingWaterPackage") + ] + ) ], products: [], dependencies: [ @@ -10843,15 +11071,18 @@ final class WorkspaceTests: XCTestCase { name: "FlowingWaterPackage", path: "flowing/water", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ] ), MockPackage( name: "Lake", targets: [ - MockTarget(name: "LakeTarget", dependencies: [ - .product(name: "StandingWaterProduct", package: "StandingWaterPackage"), - ]), + MockTarget( + name: "LakeTarget", + dependencies: [ + .product(name: "StandingWaterProduct", package: "StandingWaterPackage") + ] + ) ], products: [], dependencies: [ @@ -10859,7 +11090,7 @@ final class WorkspaceTests: XCTestCase { name: "StandingWaterPackage", path: "standing/water", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ] ), ], @@ -10868,10 +11099,10 @@ final class WorkspaceTests: XCTestCase { name: "FlowingWaterPackage", path: "flowing/water", targets: [ - MockTarget(name: "FlowingWaterTarget"), + MockTarget(name: "FlowingWaterTarget") ], products: [ - MockProduct(name: "FlowingWaterProduct", modules: ["FlowingWaterTarget"]), + MockProduct(name: "FlowingWaterProduct", modules: ["FlowingWaterTarget"]) ], versions: ["1.0.0"] ), @@ -10881,10 +11112,10 @@ final class WorkspaceTests: XCTestCase { name: "StandingWaterPackage", path: "standing/water", targets: [ - MockTarget(name: "StandingWaterTarget"), + MockTarget(name: "StandingWaterTarget") ], products: [ - MockProduct(name: "StandingWaterProduct", modules: ["StandingWaterTarget"]), + MockProduct(name: "StandingWaterProduct", modules: ["StandingWaterTarget"]) ], versions: ["1.0.0"] ), @@ -10922,10 +11153,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooUtilityProduct", package: "utility"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooUtilityProduct", package: "utility"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -10933,17 +11167,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "FooUtilityPackage", path: "foo/utility", targets: [ - MockTarget(name: "FooUtilityTarget"), + MockTarget(name: "FooUtilityTarget") ], products: [ - MockProduct(name: "FooUtilityProduct", modules: ["FooUtilityTarget"]), + MockProduct(name: "FooUtilityProduct", modules: ["FooUtilityTarget"]) ], versions: ["1.0.0"] ), @@ -10951,15 +11185,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "OtherUtilityProduct", package: "utility"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "OtherUtilityProduct", package: "utility") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .sourceControl(path: "other-foo/utility", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "other-foo/utility", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -10968,10 +11205,10 @@ final class WorkspaceTests: XCTestCase { name: "OtherUtilityPackage", path: "other-foo/utility", targets: [ - MockTarget(name: "OtherUtilityTarget"), + MockTarget(name: "OtherUtilityTarget") ], products: [ - MockProduct(name: "OtherUtilityProduct", modules: ["OtherUtilityTarget"]), + MockProduct(name: "OtherUtilityProduct", modules: ["OtherUtilityTarget"]) ], versions: ["1.0.0"] ), @@ -11008,10 +11245,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -11019,17 +11259,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://github.com/foo/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11037,18 +11277,21 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControl( url: "https://github.com/foo/foo.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11057,10 +11300,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://github.com/foo/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11083,10 +11326,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -11097,17 +11343,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://github.com/foo/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11115,15 +11361,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .sourceControl(url: "http://github.com/foo/foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "http://github.com/foo/foo", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -11132,10 +11381,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "http://github.com/foo/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11158,10 +11407,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -11172,17 +11424,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://github.com/foo/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11190,15 +11442,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .sourceControl(url: "git@github.com:foo/foo.git", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "git@github.com:foo/foo.git", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -11207,10 +11462,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "git@github.com:foo/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11233,10 +11488,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -11247,17 +11505,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://github.enterprise.com/foo/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11265,18 +11523,21 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControl( url: "git@github.enterprise.com:foo/foo.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11285,10 +11546,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "git@github.enterprise.com:foo/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11311,10 +11572,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -11325,17 +11589,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://github.com/foo/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11343,18 +11607,21 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControl( url: "https://github.com/foo-moved/foo.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11363,10 +11630,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://github.com/foo-moved/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11397,11 +11664,14 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - .product(name: "BazProduct", package: "baz"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + .product(name: "BazProduct", package: "baz"), + ] + ) ], products: [], dependencies: [ @@ -11419,17 +11689,17 @@ final class WorkspaceTests: XCTestCase { ), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://github.com/org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11437,13 +11707,16 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", url: "https://github.com/org/bar.git", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "Foo"), - .product(name: "BazProduct", package: "baz"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "Foo"), + .product(name: "BazProduct", package: "baz"), + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControl( @@ -11458,10 +11731,10 @@ final class WorkspaceTests: XCTestCase { name: "BazPackage", url: "https://github.com/org/baz.git", targets: [ - MockTarget(name: "BazTarget"), + MockTarget(name: "BazTarget") ], products: [ - MockProduct(name: "BazProduct", modules: ["BazTarget"]), + MockProduct(name: "BazProduct", modules: ["BazTarget"]) ], versions: ["1.0.0"] ), @@ -11470,10 +11743,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://github.com/ORG/Foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11482,10 +11755,10 @@ final class WorkspaceTests: XCTestCase { name: "BazPackage", url: "https://github.com/org/baz", targets: [ - MockTarget(name: "BazTarget"), + MockTarget(name: "BazTarget") ], products: [ - MockProduct(name: "BazProduct", modules: ["BazTarget"]), + MockProduct(name: "BazProduct", modules: ["BazTarget"]) ], versions: ["1.0.0"] ), @@ -11519,9 +11792,12 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooUtilityProduct", package: "FooUtilityPackage"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooUtilityProduct", package: "FooUtilityPackage") + ] + ) ], products: [], dependencies: [ @@ -11529,29 +11805,32 @@ final class WorkspaceTests: XCTestCase { name: "FooUtilityPackage", path: "foo/utility", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], toolsVersion: .v6_0 - ), + ) ], packages: [ MockPackage( name: "FooUtilityPackage", path: "foo/utility", targets: [ - MockTarget(name: "FooUtilityTarget", dependencies: [ - .product(name: "BarProduct", package: "BarPackage"), - ]), + MockTarget( + name: "FooUtilityTarget", + dependencies: [ + .product(name: "BarProduct", package: "BarPackage") + ] + ) ], products: [ - MockProduct(name: "FooUtilityProduct", modules: ["FooUtilityTarget"]), + MockProduct(name: "FooUtilityProduct", modules: ["FooUtilityTarget"]) ], dependencies: [ .sourceControlWithDeprecatedName( name: "BarPackage", path: "bar", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11559,19 +11838,22 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "OtherUtilityProduct", package: "OtherUtilityPackage"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "OtherUtilityProduct", package: "OtherUtilityPackage") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControlWithDeprecatedName( name: "OtherUtilityPackage", path: "other/utility", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11580,10 +11862,10 @@ final class WorkspaceTests: XCTestCase { name: "OtherUtilityPackage", path: "other/utility", targets: [ - MockTarget(name: "OtherUtilityTarget"), + MockTarget(name: "OtherUtilityTarget") ], products: [ - MockProduct(name: "OtherUtilityProduct", modules: ["OtherUtilityTarget"]), + MockProduct(name: "OtherUtilityProduct", modules: ["OtherUtilityTarget"]) ], versions: ["1.0.0"] ), @@ -11612,31 +11894,37 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooUtilityProduct", package: "FooUtilityPackage"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooUtilityProduct", package: "FooUtilityPackage") + ] + ) ], products: [], dependencies: [ - .sourceControl(path: "foo/utility", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "foo/utility", requirement: .upToNextMajor(from: "1.0.0")) ], toolsVersion: .v5 - ), + ) ], packages: [ MockPackage( name: "FooUtilityPackage", path: "foo/utility", targets: [ - MockTarget(name: "FooUtilityTarget", dependencies: [ - .product(name: "BarProduct", package: "BarPackage"), - ]), + MockTarget( + name: "FooUtilityTarget", + dependencies: [ + .product(name: "BarProduct", package: "BarPackage") + ] + ) ], products: [ - MockProduct(name: "FooUtilityProduct", modules: ["FooUtilityTarget"]), + MockProduct(name: "FooUtilityProduct", modules: ["FooUtilityTarget"]) ], dependencies: [ - .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"], toolsVersion: .v5 @@ -11645,15 +11933,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "OtherUtilityProduct", package: "OtherUtilityPackage"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "OtherUtilityProduct", package: "OtherUtilityPackage") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .sourceControl(path: "other/utility", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(path: "other/utility", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"], toolsVersion: .v5 @@ -11663,10 +11954,10 @@ final class WorkspaceTests: XCTestCase { name: "OtherUtilityPackage", path: "other/utility", targets: [ - MockTarget(name: "OtherUtilityTarget"), + MockTarget(name: "OtherUtilityTarget") ], products: [ - MockProduct(name: "OtherUtilityProduct", modules: ["OtherUtilityTarget"]), + MockProduct(name: "OtherUtilityProduct", modules: ["OtherUtilityTarget"]) ], versions: ["1.0.0"] ), @@ -11697,9 +11988,12 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "foo", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "BarProduct", package: "BarPackage"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "BarProduct", package: "BarPackage") + ] + ) ], products: [], dependencies: [ @@ -11707,29 +12001,32 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", path: "bar", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], toolsVersion: .v6_0 - ), + ) ], packages: [ MockPackage( name: "BarPackage", path: "bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "FooPackage"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "FooPackage") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControlWithDeprecatedName( name: "FooPackage", path: "foo", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11738,10 +12035,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", path: "foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11771,11 +12068,14 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "BarProduct", package: "bar"), - .product(name: "BazProduct", package: "baz"), - .product(name: "QuxProduct", package: "qux"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "BarProduct", package: "bar"), + .product(name: "BazProduct", package: "baz"), + .product(name: "QuxProduct", package: "qux"), + ] + ) ], dependencies: [ .sourceControl( @@ -11791,25 +12091,28 @@ final class WorkspaceTests: XCTestCase { requirement: .upToNextMajor(from: "1.0.0") ), ] - ), + ) ], packages: [ MockPackage( name: "BarPackage", url: "https://github.com/org/bar.git", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControl( url: "http://github.com/org/foo", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11817,10 +12120,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "http://github.com/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11828,18 +12131,21 @@ final class WorkspaceTests: XCTestCase { name: "BazPackage", url: "https://github.com/org/baz.git", targets: [ - MockTarget(name: "BazTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BazTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BazProduct", modules: ["BazTarget"]), + MockProduct(name: "BazProduct", modules: ["BazTarget"]) ], dependencies: [ .sourceControl( url: "git@github.com:org/foo.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11847,10 +12153,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "git@github.com:org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11858,18 +12164,21 @@ final class WorkspaceTests: XCTestCase { name: "QuxPackage", url: "https://github.com/org/qux.git", targets: [ - MockTarget(name: "QuxTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "QuxTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "QuxProduct", modules: ["QuxTarget"]), + MockProduct(name: "QuxProduct", modules: ["QuxTarget"]) ], dependencies: [ .sourceControl( url: "https://github.com/org/foo.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11877,10 +12186,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://github.com/org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11932,11 +12241,14 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - .product(name: "BazProduct", package: "baz"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + .product(name: "BazProduct", package: "baz"), + ] + ) ], dependencies: [ .sourceControl( @@ -11952,17 +12264,17 @@ final class WorkspaceTests: XCTestCase { requirement: .upToNextMajor(from: "1.0.0") ), ] - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "git@github.com:org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -11970,18 +12282,21 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", url: "https://github.com/org/bar.git", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControl( url: "http://github.com/org/foo", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -11989,10 +12304,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "http://github.com/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -12000,18 +12315,21 @@ final class WorkspaceTests: XCTestCase { name: "BazPackage", url: "https://github.com/org/baz.git", targets: [ - MockTarget(name: "BazTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BazTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BazProduct", modules: ["BazTarget"]), + MockProduct(name: "BazProduct", modules: ["BazTarget"]) ], dependencies: [ .sourceControl( url: "https://github.com/org/foo.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -12019,10 +12337,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://github.com/org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -12071,24 +12389,30 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "BarProduct", package: "bar") + ] + ) ], dependencies: [ .sourceControl( url: "https://github.com/org/bar.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ] ), MockPackage( name: "Root2", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "BarProduct", package: "bar"), - .product(name: "BazProduct", package: "baz"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "BarProduct", package: "bar"), + .product(name: "BazProduct", package: "baz"), + ] + ) ], dependencies: [ .sourceControl( @@ -12107,65 +12431,71 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://github.com/org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0"], - revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work + revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work ), MockPackage( name: "FooPackage", url: "git@github.com:org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0"], - revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work + revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work ), MockPackage( name: "BarPackage", url: "https://github.com/org/bar.git", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControl( url: "git@github.com:org/foo.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0", "1.1.0", "1.2.0"], - revisionProvider: { _ in "bar" } // we need this to be consistent for fingerprints check to work + revisionProvider: { _ in "bar" } // we need this to be consistent for fingerprints check to work ), MockPackage( name: "BazPackage", url: "https://github.com/org/baz.git", targets: [ - MockTarget(name: "BazTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BazTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BazProduct", modules: ["BazTarget"]), + MockProduct(name: "BazProduct", modules: ["BazTarget"]) ], dependencies: [ .sourceControl( url: "https://github.com/org/foo", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0", "1.1.0", "1.2.0"], - revisionProvider: { _ in "baz" } // we need this to be consistent for fingerprints check to work + revisionProvider: { _ in "baz" } // we need this to be consistent for fingerprints check to work ), ] ) @@ -12233,29 +12563,35 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], dependencies: [ .sourceControl( url: "https://github.com/org/foo.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ] ), MockPackage( name: "Root2", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], dependencies: [ .sourceControl( url: "git@github.com:org/foo.git", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ] ), ], @@ -12264,25 +12600,25 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://github.com/org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"], - revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work + revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work ), MockPackage( name: "FooPackage", url: "git@github.com:org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"], - revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work + revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work ), ] ) @@ -12346,10 +12682,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], dependencies: [ .sourceControl( @@ -12365,10 +12704,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root2", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], dependencies: [ .sourceControl( @@ -12387,30 +12729,33 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://github.com/org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"], - revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work + revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work ), MockPackage( name: "BarPackage", url: "https://github.com/org/bar.git", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControl( url: "http://github.com/org/foo", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -12418,25 +12763,25 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "http://github.com/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"], - revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work + revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work ), MockPackage( name: "FooPackage", url: "git@github.com:org/foo.git", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"], - revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work + revisionProvider: { _ in "foo" } // we need this to be consistent for fingerprints check to work ), ] ) @@ -12512,13 +12857,16 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root1", targets: [ - .init(name: "Root1Target", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "Root2Product", package: "Root2"), - ]), + .init( + name: "Root1Target", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "Root2Product", package: "Root2"), + ] + ) ], products: [ - .init(name: "Root1Product", modules: ["Root1Target"]), + .init(name: "Root1Product", modules: ["Root1Target"]) ], dependencies: [ .sourceControl( @@ -12531,18 +12879,21 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root2", targets: [ - .init(name: "Root2Target", dependencies: [ - .product(name: "BarProduct", package: "bar"), - ]), + .init( + name: "Root2Target", + dependencies: [ + .product(name: "BarProduct", package: "bar") + ] + ) ], products: [ - .init(name: "Root2Product", modules: ["Root2Target"]), + .init(name: "Root2Product", modules: ["Root2Target"]) ], dependencies: [ .sourceControl( url: "http://scm.com/org/bar", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ] ), ], @@ -12551,18 +12902,21 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "http://scm.com/org/foo", targets: [ - .init(name: "FooTarget", dependencies: [ - .product(name: "BarProduct", package: "bar"), - ]), + .init( + name: "FooTarget", + dependencies: [ + .product(name: "BarProduct", package: "bar") + ] + ) ], products: [ - .init(name: "FooProduct", modules: ["FooTarget"]), + .init(name: "FooProduct", modules: ["FooTarget"]) ], dependencies: [ .sourceControl( url: "http://scm.com/org/bar", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -12570,18 +12924,21 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", url: "http://scm.com/org/bar", targets: [ - .init(name: "BarTarget", dependencies: [ - .product(name: "BazProduct", package: "baz"), - ]), + .init( + name: "BarTarget", + dependencies: [ + .product(name: "BazProduct", package: "baz") + ] + ) ], products: [ - .init(name: "BarProduct", modules: ["BarTarget"]), + .init(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ .sourceControl( url: "http://scm.com/org/baz", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -12589,18 +12946,21 @@ final class WorkspaceTests: XCTestCase { name: "BazPackage", url: "http://scm.com/org/baz", targets: [ - .init(name: "BazTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + .init( + name: "BazTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - .init(name: "BazProduct", modules: ["BazTarget"]), + .init(name: "BazProduct", modules: ["BazTarget"]) ], dependencies: [ .sourceControl( url: "http://scm.com/org/foo", requirement: .upToNextMajor(from: "1.0.0") - ), + ) ], versions: ["1.0.0"] ), @@ -12628,10 +12988,13 @@ final class WorkspaceTests: XCTestCase { MockPackage( name: "Root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -12639,17 +13002,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(url: "http://localhost/org/bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "http://localhost/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "experiment"] ), @@ -12657,15 +13020,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", url: "http://localhost/org/bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .sourceControl(url: "http://localhost/org/foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "http://localhost/org/foo", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -12697,15 +13063,15 @@ final class WorkspaceTests: XCTestCase { try fs.writeFileContents( foo.appending("Package.swift"), string: """ - // swift-tools-version:5.3 - import PackageDescription - let package = Package( - name: "Best", - targets: [ - .binaryTarget(name: "best", path: "/best.xcframework") - ] - ) - """ + // swift-tools-version:5.3 + import PackageDescription + let package = Package( + name: "Best", + targets: [ + .binaryTarget(name: "best", path: "/best.xcframework") + ] + ) + """ ) let manifestLoader = try ManifestLoader(toolchain: UserToolchain.default) @@ -12836,34 +13202,34 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget1", dependencies: [ - .product(name: "Foo", package: "foo"), + .product(name: "Foo", package: "foo") ] ), MockTarget( name: "MyTarget2", dependencies: [ - .product(name: "Bar", package: "bar"), + .product(name: "Bar", package: "bar") ] ), ], products: [ - MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]), + MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]) ], dependencies: [ .sourceControl(url: "http://localhost/org/foo", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(url: "http://localhost/org/bar", requirement: .upToNextMajor(from: "2.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Foo", url: "http://localhost/org/foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.1.0", "1.2.0", "1.3.0", "1.4.0", "1.5.0", "1.5.1"] ), @@ -12871,10 +13237,10 @@ final class WorkspaceTests: XCTestCase { name: "Bar", url: "http://localhost/org/bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["2.0.0", "2.1.0", "2.2.0"] ), @@ -12901,13 +13267,13 @@ final class WorkspaceTests: XCTestCase { XCTAssertMatch( workspace.delegate.events, [ - "will load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)", + "will load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)" ] ) XCTAssertMatch( workspace.delegate.events, [ - "did load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)", + "did load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)" ] ) XCTAssertMatch( @@ -12942,24 +13308,24 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget1", dependencies: [ - .product(name: "Foo", package: "foo"), + .product(name: "Foo", package: "foo") ] ), MockTarget( name: "MyTarget2", dependencies: [ - .product(name: "Bar", package: "bar"), + .product(name: "Bar", package: "bar") ] ), ], products: [ - MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]), + MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]) ], dependencies: [ .sourceControl(url: "http://localhost/org/foo", requirement: .upToNextMajor(from: "1.0.0")), .sourceControl(url: "http://localhost/org/bar", requirement: .upToNextMajor(from: "2.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -12969,15 +13335,15 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "Foo", dependencies: [ - .product(name: "Baz", package: "baz"), + .product(name: "Baz", package: "baz") ] - ), + ) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .sourceControl(url: "http://localhost/org/baz", requirement: .range("2.0.0" ..< "4.0.0")), + .sourceControl(url: "http://localhost/org/baz", requirement: .range("2.0.0"..<"4.0.0")) ], versions: ["1.0.0", "1.1.0"] ), @@ -12988,15 +13354,15 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "Bar", dependencies: [ - .product(name: "Baz", package: "baz"), + .product(name: "Baz", package: "baz") ] - ), + ) ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], dependencies: [ - .sourceControl(url: "http://localhost/org/baz", requirement: .upToNextMajor(from: "3.0.0")), + .sourceControl(url: "http://localhost/org/baz", requirement: .upToNextMajor(from: "3.0.0")) ], versions: ["2.0.0", "2.1.0"] ), @@ -13004,10 +13370,10 @@ final class WorkspaceTests: XCTestCase { name: "Baz", url: "http://localhost/org/baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.1.0", "2.0.0", "2.1.0", "3.0.0", "3.1.0"] ), @@ -13037,13 +13403,13 @@ final class WorkspaceTests: XCTestCase { XCTAssertMatch( workspace.delegate.events, [ - "will load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)", + "will load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)" ] ) XCTAssertMatch( workspace.delegate.events, [ - "did load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)", + "did load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)" ] ) XCTAssertMatch( @@ -13086,34 +13452,34 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget1", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] ), MockTarget( name: "MyTarget2", dependencies: [ - .product(name: "Bar", package: "org.bar"), + .product(name: "Bar", package: "org.bar") ] ), ], products: [ - MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]), + MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]) ], dependencies: [ .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), .registry(identity: "org.bar", requirement: .upToNextMajor(from: "2.0.0")), ] - ), + ) ], packages: [ MockPackage( name: "Foo", identity: "org.foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.1.0", "1.2.0", "1.3.0", "1.4.0", "1.5.0", "1.5.1"] ), @@ -13121,10 +13487,10 @@ final class WorkspaceTests: XCTestCase { name: "Bar", identity: "org.bar", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["2.0.0", "2.1.0", "2.2.0"] ), @@ -13151,13 +13517,13 @@ final class WorkspaceTests: XCTestCase { XCTAssertMatch( workspace.delegate.events, [ - "will load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)", + "will load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)" ] ) XCTAssertMatch( workspace.delegate.events, [ - "did load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)", + "did load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)" ] ) XCTAssertMatch( @@ -13192,24 +13558,24 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget1", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] ), MockTarget( name: "MyTarget2", dependencies: [ - .product(name: "Bar", package: "org.bar"), + .product(name: "Bar", package: "org.bar") ] ), ], products: [ - MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]), + MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]) ], dependencies: [ .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), .registry(identity: "org.bar", requirement: .upToNextMajor(from: "2.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -13219,15 +13585,15 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "Foo", dependencies: [ - .product(name: "Baz", package: "org.baz"), + .product(name: "Baz", package: "org.baz") ] - ), + ) ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], dependencies: [ - .registry(identity: "org.baz", requirement: .range("2.0.0" ..< "4.0.0")), + .registry(identity: "org.baz", requirement: .range("2.0.0"..<"4.0.0")) ], versions: ["1.0.0", "1.1.0"] ), @@ -13238,15 +13604,15 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "Bar", dependencies: [ - .product(name: "Baz", package: "org.baz"), + .product(name: "Baz", package: "org.baz") ] - ), + ) ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], dependencies: [ - .registry(identity: "org.baz", requirement: .upToNextMajor(from: "3.0.0")), + .registry(identity: "org.baz", requirement: .upToNextMajor(from: "3.0.0")) ], versions: ["1.0.0", "1.1.0", "2.0.0", "2.1.0"] ), @@ -13254,10 +13620,10 @@ final class WorkspaceTests: XCTestCase { name: "Baz", identity: "org.baz", targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0", "1.1.0", "2.0.0", "2.1.0", "3.0.0", "3.1.0"] ), @@ -13287,13 +13653,13 @@ final class WorkspaceTests: XCTestCase { XCTAssertMatch( workspace.delegate.events, [ - "will load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)", + "will load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)" ] ) XCTAssertMatch( workspace.delegate.events, [ - "did load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)", + "did load manifest for root package: \(sandbox.appending(components: "roots", "MyPackage")) (identity: mypackage)" ] ) XCTAssertMatch( @@ -13334,16 +13700,19 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [], dependencies: [ - .sourceControl(url: "https://git/org/foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://git/org/foo", requirement: .upToNextMajor(from: "1.0.0")) ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( @@ -13351,10 +13720,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.bar", alternativeURLs: ["https://git/org/Bar"], targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "Bar", modules: ["BarTarget"]), + MockProduct(name: "Bar", modules: ["BarTarget"]) ], versions: ["1.0.0", "1.1.0"] ), @@ -13363,15 +13732,18 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget", dependencies: [ - "Bar", - ]), + MockTarget( + name: "FooTarget", + dependencies: [ + "Bar" + ] + ) ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], dependencies: [ - .sourceControl(url: "https://git/org/Bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://git/org/Bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0", "1.1.0", "1.2.0"] ), @@ -13414,10 +13786,13 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "org.bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "org.bar"), + ] + ) ], products: [], dependencies: [ @@ -13425,17 +13800,17 @@ final class WorkspaceTests: XCTestCase { .registry(identity: "org.bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://git/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0", "1.2.0"] ), @@ -13443,10 +13818,10 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", identity: "org.bar", targets: [ - MockTarget(name: "BarTarget"), + MockTarget(name: "BarTarget") ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], versions: ["1.0.0", "1.1.0"] ), @@ -13455,10 +13830,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0", "1.2.0"] ), @@ -13544,16 +13919,19 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "Foo"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "Foo") + ] + ) ], products: [], dependencies: [ - .sourceControl(url: "https://git/org/foo", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://git/org/foo", requirement: .upToNextMajor(from: "1.0.0")) ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( @@ -13561,16 +13939,16 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], dependencies: [ - .sourceControl(url: "https://git/org/bar", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://git/org/bar", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0", "1.1.0", "1.2.0"] - ), + ) ] ) @@ -13609,9 +13987,12 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [], dependencies: [ @@ -13619,17 +14000,17 @@ final class WorkspaceTests: XCTestCase { .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://git/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -13638,10 +14019,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -13651,8 +14032,10 @@ final class WorkspaceTests: XCTestCase { do { workspace.sourceControlToRegistryDependencyTransformation = .disabled - await XCTAssertAsyncThrowsError(try await workspace.checkPackageGraph(roots: ["root"]) { _, _ in - }) { error in + await XCTAssertAsyncThrowsError( + try await workspace.checkPackageGraph(roots: ["root"]) { _, _ in + } + ) { error in XCTAssertEqual( (error as? PackageGraphError)?.description, "multiple packages (\'foo\' (from \'https://git/org/foo\'), \'org.foo\') declare products with a conflicting name: \'FooProduct’; product names need to be unique across the package graph" @@ -13708,10 +14091,13 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -13719,17 +14105,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(url: "https://git/org/bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://git/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0", "2.0.0", "2.1.0"] ), @@ -13737,15 +14123,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", url: "https://git/org/bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "org.foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "org.foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0", "1.1.0", "2.0.0", "2.1.0"] ), @@ -13754,10 +14143,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0", "2.0.0", "2.1.0"] ), @@ -13769,9 +14158,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' - """), + diagnostic: .contains( + """ + multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' + """ + ), severity: .error ) } @@ -13788,9 +14179,11 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( - diagnostic: .contains(""" - dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. - """), + diagnostic: .contains( + """ + dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. + """ + ), severity: .warning ) } @@ -13872,10 +14265,13 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "org.bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "org.bar"), + ] + ) ], products: [], dependencies: [ @@ -13883,17 +14279,17 @@ final class WorkspaceTests: XCTestCase { .registry(identity: "org.bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://git/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0", "1.2.0"] ), @@ -13901,15 +14297,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", identity: "org.bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "org.foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "org.foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.2.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.2.0")) ], versions: ["1.0.0", "1.1.0"] ), @@ -13918,10 +14317,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0", "1.2.0"] ), @@ -13933,9 +14332,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' - """), + diagnostic: .contains( + """ + multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' + """ + ), severity: .error ) } @@ -13952,9 +14353,11 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( - diagnostic: .contains(""" - dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. - """), + diagnostic: .contains( + """ + dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. + """ + ), severity: .warning ) } @@ -14011,10 +14414,13 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "bar"), + ] + ) ], products: [], dependencies: [ @@ -14022,17 +14428,17 @@ final class WorkspaceTests: XCTestCase { .sourceControl(url: "https://git/org/bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://git/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -14040,15 +14446,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", url: "https://git/org/bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "org.foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "org.foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "2.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "2.0.0")) ], versions: ["1.0.0"] ), @@ -14057,10 +14466,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -14072,9 +14481,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' - """), + diagnostic: .contains( + """ + multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' + """ + ), severity: .error ) } @@ -14091,10 +14502,10 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check( diagnostic: - """ - Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'bar' 1.0.0..<2.0.0. - 'bar' >= 1.0.0 practically depends on 'org.foo' 2.0.0..<3.0.0 because no versions of 'bar' match the requirement 1.0.1..<2.0.0 and 'bar' 1.0.0 depends on 'org.foo' 2.0.0..<3.0.0. - """, + """ + Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'bar' 1.0.0..<2.0.0. + 'bar' >= 1.0.0 practically depends on 'org.foo' 2.0.0..<3.0.0 because no versions of 'bar' match the requirement 1.0.1..<2.0.0 and 'bar' 1.0.0 depends on 'org.foo' 2.0.0..<3.0.0. + """, severity: .error ) } @@ -14111,10 +14522,10 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check( diagnostic: - """ - Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'bar' 1.0.0..<2.0.0. - 'bar' >= 1.0.0 practically depends on 'org.foo' 2.0.0..<3.0.0 because no versions of 'bar' match the requirement 1.0.1..<2.0.0 and 'bar' 1.0.0 depends on 'org.foo' 2.0.0..<3.0.0. - """, + """ + Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'bar' 1.0.0..<2.0.0. + 'bar' >= 1.0.0 practically depends on 'org.foo' 2.0.0..<3.0.0 because no versions of 'bar' match the requirement 1.0.1..<2.0.0 and 'bar' 1.0.0 depends on 'org.foo' 2.0.0..<3.0.0. + """, severity: .error ) } @@ -14136,10 +14547,13 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "org.foo"), - .product(name: "BarProduct", package: "org.bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "org.foo"), + .product(name: "BarProduct", package: "org.bar"), + ] + ) ], products: [], dependencies: [ @@ -14147,7 +14561,7 @@ final class WorkspaceTests: XCTestCase { .registry(identity: "org.bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( @@ -14155,10 +14569,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0", "1.2.0"] ), @@ -14166,15 +14580,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", identity: "org.bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .sourceControl(url: "https://git/org/foo", requirement: .upToNextMajor(from: "1.2.0")), + .sourceControl(url: "https://git/org/foo", requirement: .upToNextMajor(from: "1.2.0")) ], versions: ["1.0.0", "1.1.0"] ), @@ -14182,10 +14599,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://git/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "1.1.0", "1.2.0"] ), @@ -14197,9 +14614,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' - """), + diagnostic: .contains( + """ + multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' + """ + ), severity: .error ) } @@ -14216,16 +14635,20 @@ final class WorkspaceTests: XCTestCase { let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - dependency 'git/org/foo' and dependency 'org.foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->git/org/foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->org.foo. - """), + diagnostic: .contains( + """ + dependency 'git/org/foo' and dependency 'org.foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->git/org/foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->org.foo. + """ + ), severity: .warning ) if ToolsVersion.current >= .v5_8 { result.check( - diagnostic: .contains(""" - product 'FooProduct' required by package 'org.bar' target 'BarTarget' not found in package 'foo'. - """), + diagnostic: .contains( + """ + product 'FooProduct' required by package 'org.bar' target 'BarTarget' not found in package 'foo'. + """ + ), severity: .error ) } @@ -14283,10 +14706,13 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "org.foo"), - .product(name: "BarProduct", package: "org.bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "org.foo"), + .product(name: "BarProduct", package: "org.bar"), + ] + ) ], products: [], dependencies: [ @@ -14294,7 +14720,7 @@ final class WorkspaceTests: XCTestCase { .registry(identity: "org.bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( @@ -14302,10 +14728,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -14313,15 +14739,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", identity: "org.bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .sourceControl(url: "https://git/org/foo", requirement: .upToNextMajor(from: "2.0.0")), + .sourceControl(url: "https://git/org/foo", requirement: .upToNextMajor(from: "2.0.0")) ], versions: ["1.0.0"] ), @@ -14329,10 +14758,10 @@ final class WorkspaceTests: XCTestCase { name: "FooPackage", url: "https://git/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -14344,9 +14773,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' - """), + diagnostic: .contains( + """ + multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' + """ + ), severity: .error ) } @@ -14363,10 +14794,10 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check( diagnostic: - """ - Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'org.bar' 1.0.0..<2.0.0. - 'org.bar' >= 1.0.0 practically depends on 'org.foo' 2.0.0..<3.0.0 because no versions of 'org.bar' match the requirement 1.0.1..<2.0.0 and 'org.bar' 1.0.0 depends on 'org.foo' 2.0.0..<3.0.0. - """, + """ + Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'org.bar' 1.0.0..<2.0.0. + 'org.bar' >= 1.0.0 practically depends on 'org.foo' 2.0.0..<3.0.0 because no versions of 'org.bar' match the requirement 1.0.1..<2.0.0 and 'org.bar' 1.0.0 depends on 'org.foo' 2.0.0..<3.0.0. + """, severity: .error ) } @@ -14383,10 +14814,10 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check( diagnostic: - """ - Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'org.bar' 1.0.0..<2.0.0. - 'org.bar' >= 1.0.0 practically depends on 'org.foo' 2.0.0..<3.0.0 because no versions of 'org.bar' match the requirement 1.0.1..<2.0.0 and 'org.bar' 1.0.0 depends on 'org.foo' 2.0.0..<3.0.0. - """, + """ + Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'org.bar' 1.0.0..<2.0.0. + 'org.bar' >= 1.0.0 practically depends on 'org.foo' 2.0.0..<3.0.0 because no versions of 'org.bar' match the requirement 1.0.1..<2.0.0 and 'org.bar' 1.0.0 depends on 'org.foo' 2.0.0..<3.0.0. + """, severity: .error ) } @@ -14408,10 +14839,13 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "org.foo"), - .product(name: "BarProduct", package: "org.bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "org.foo"), + .product(name: "BarProduct", package: "org.bar"), + ] + ) ], products: [], dependencies: [ @@ -14419,22 +14853,25 @@ final class WorkspaceTests: XCTestCase { .registry(identity: "org.bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", identity: "org.foo", targets: [ - MockTarget(name: "FooTarget", dependencies: [ - .product(name: "BazProduct", package: "baz"), - ]), + MockTarget( + name: "FooTarget", + dependencies: [ + .product(name: "BazProduct", package: "baz") + ] + ) ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], dependencies: [ - .sourceControl(url: "https://git/org/baz", requirement: .upToNextMajor(from: "1.1.0")), + .sourceControl(url: "https://git/org/baz", requirement: .upToNextMajor(from: "1.1.0")) ], versions: ["1.0.0"] ), @@ -14442,15 +14879,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", identity: "org.bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "BazProduct", package: "org.baz"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "BazProduct", package: "org.baz") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .registry(identity: "org.baz", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.baz", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -14458,10 +14898,10 @@ final class WorkspaceTests: XCTestCase { name: "BazPackage", url: "https://git/org/baz", targets: [ - MockTarget(name: "BazTarget"), + MockTarget(name: "BazTarget") ], products: [ - MockProduct(name: "BazProduct", modules: ["BazTarget"]), + MockProduct(name: "BazProduct", modules: ["BazTarget"]) ], versions: ["1.0.0", "1.1.0"] ), @@ -14470,10 +14910,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.baz", alternativeURLs: ["https://git/org/baz"], targets: [ - MockTarget(name: "BazTarget"), + MockTarget(name: "BazTarget") ], products: [ - MockProduct(name: "BazProduct", modules: ["BazTarget"]), + MockProduct(name: "BazProduct", modules: ["BazTarget"]) ], versions: ["1.0.0", "1.1.0"] ), @@ -14485,9 +14925,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - multiple similar targets 'BazTarget' appear in registry package 'org.baz' and source control package 'baz' - """), + diagnostic: .contains( + """ + multiple similar targets 'BazTarget' appear in registry package 'org.baz' and source control package 'baz' + """ + ), severity: .error ) } @@ -14504,16 +14946,20 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( - diagnostic: .contains(""" - dependency 'git/org/baz' and dependency 'org.baz' both point to the same package identity 'org.baz'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.foo->git/org/baz (B) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.baz. - """), + diagnostic: .contains( + """ + dependency 'git/org/baz' and dependency 'org.baz' both point to the same package identity 'org.baz'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.foo->git/org/baz (B) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.baz. + """ + ), severity: .warning ) if ToolsVersion.current >= .v5_8 { result.check( - diagnostic: .contains(""" - product 'BazProduct' required by package 'org.foo' target 'FooTarget' not found in package 'baz'. - """), + diagnostic: .contains( + """ + product 'BazProduct' required by package 'org.foo' target 'FooTarget' not found in package 'baz'. + """ + ), severity: .error ) } @@ -14579,10 +15025,13 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "org.foo"), - .product(name: "BarProduct", package: "org.bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "org.foo"), + .product(name: "BarProduct", package: "org.bar"), + ] + ) ], products: [], dependencies: [ @@ -14590,22 +15039,25 @@ final class WorkspaceTests: XCTestCase { .registry(identity: "org.bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", identity: "org.foo", targets: [ - MockTarget(name: "FooTarget", dependencies: [ - .product(name: "BazProduct", package: "baz"), - ]), + MockTarget( + name: "FooTarget", + dependencies: [ + .product(name: "BazProduct", package: "baz") + ] + ) ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], dependencies: [ - .sourceControl(url: "https://git/org/baz", requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: "https://git/org/baz", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -14613,15 +15065,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", identity: "org.bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "BazProduct", package: "org.baz"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "BazProduct", package: "org.baz") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .registry(identity: "org.baz", requirement: .upToNextMajor(from: "2.0.0")), + .registry(identity: "org.baz", requirement: .upToNextMajor(from: "2.0.0")) ], versions: ["1.0.0"] ), @@ -14629,10 +15084,10 @@ final class WorkspaceTests: XCTestCase { name: "BazPackage", url: "https://git/org/baz", targets: [ - MockTarget(name: "BazTarget"), + MockTarget(name: "BazTarget") ], products: [ - MockProduct(name: "BazProduct", modules: ["BazTarget"]), + MockProduct(name: "BazProduct", modules: ["BazTarget"]) ], versions: ["1.0.0"] ), @@ -14641,10 +15096,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.baz", alternativeURLs: ["https://git/org/baz"], targets: [ - MockTarget(name: "BazTarget"), + MockTarget(name: "BazTarget") ], products: [ - MockProduct(name: "BazProduct", modules: ["BazTarget"]), + MockProduct(name: "BazProduct", modules: ["BazTarget"]) ], versions: ["1.0.0", "2.0.0"] ), @@ -14656,9 +15111,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - multiple similar targets 'BazTarget' appear in registry package 'org.baz' and source control package 'baz' - """), + diagnostic: .contains( + """ + multiple similar targets 'BazTarget' appear in registry package 'org.baz' and source control package 'baz' + """ + ), severity: .error ) } @@ -14675,10 +15132,10 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check( diagnostic: """ - Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'org.bar' 1.0.0..<2.0.0. - 'org.bar' is incompatible with 'org.foo' because 'org.foo' 1.0.0 depends on 'org.baz' 1.0.0..<2.0.0 and no versions of 'org.foo' match the requirement 1.0.1..<2.0.0. - 'org.bar' >= 1.0.0 practically depends on 'org.baz' 2.0.0..<3.0.0 because no versions of 'org.bar' match the requirement 1.0.1..<2.0.0 and 'org.bar' 1.0.0 depends on 'org.baz' 2.0.0..<3.0.0. - """, + Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'org.bar' 1.0.0..<2.0.0. + 'org.bar' is incompatible with 'org.foo' because 'org.foo' 1.0.0 depends on 'org.baz' 1.0.0..<2.0.0 and no versions of 'org.foo' match the requirement 1.0.1..<2.0.0. + 'org.bar' >= 1.0.0 practically depends on 'org.baz' 2.0.0..<3.0.0 because no versions of 'org.bar' match the requirement 1.0.1..<2.0.0 and 'org.bar' 1.0.0 depends on 'org.baz' 2.0.0..<3.0.0. + """, severity: .error ) } @@ -14695,10 +15152,10 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check( diagnostic: """ - Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'org.bar' 1.0.0..<2.0.0. - 'org.bar' is incompatible with 'org.foo' because 'org.foo' 1.0.0 depends on 'org.baz' 1.0.0..<2.0.0 and no versions of 'org.foo' match the requirement 1.0.1..<2.0.0. - 'org.bar' >= 1.0.0 practically depends on 'org.baz' 2.0.0..<3.0.0 because no versions of 'org.bar' match the requirement 1.0.1..<2.0.0 and 'org.bar' 1.0.0 depends on 'org.baz' 2.0.0..<3.0.0. - """, + Dependencies could not be resolved because root depends on 'org.foo' 1.0.0..<2.0.0 and root depends on 'org.bar' 1.0.0..<2.0.0. + 'org.bar' is incompatible with 'org.foo' because 'org.foo' 1.0.0 depends on 'org.baz' 1.0.0..<2.0.0 and no versions of 'org.foo' match the requirement 1.0.1..<2.0.0. + 'org.bar' >= 1.0.0 practically depends on 'org.baz' 2.0.0..<3.0.0 because no versions of 'org.bar' match the requirement 1.0.1..<2.0.0 and 'org.bar' 1.0.0 depends on 'org.baz' 2.0.0..<3.0.0. + """, severity: .error ) } @@ -14721,10 +15178,13 @@ final class WorkspaceTests: XCTestCase { name: "Root", path: "root", targets: [ - MockTarget(name: "RootTarget", dependencies: [ - .product(name: "FooProduct", package: "foo"), - .product(name: "BarProduct", package: "org.bar"), - ]), + MockTarget( + name: "RootTarget", + dependencies: [ + .product(name: "FooProduct", package: "foo"), + .product(name: "BarProduct", package: "org.bar"), + ] + ) ], products: [], dependencies: [ @@ -14732,17 +15192,17 @@ final class WorkspaceTests: XCTestCase { .registry(identity: "org.bar", requirement: .upToNextMajor(from: "1.0.0")), ], toolsVersion: .v5_6 - ), + ) ], packages: [ MockPackage( name: "FooPackage", url: "https://git/org/foo", targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["experiment"] ), @@ -14750,15 +15210,18 @@ final class WorkspaceTests: XCTestCase { name: "BarPackage", identity: "org.bar", targets: [ - MockTarget(name: "BarTarget", dependencies: [ - .product(name: "FooProduct", package: "org.foo"), - ]), + MockTarget( + name: "BarTarget", + dependencies: [ + .product(name: "FooProduct", package: "org.foo") + ] + ) ], products: [ - MockProduct(name: "BarProduct", modules: ["BarTarget"]), + MockProduct(name: "BarProduct", modules: ["BarTarget"]) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ], versions: ["1.0.0"] ), @@ -14767,10 +15230,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", alternativeURLs: ["https://git/org/foo"], targets: [ - MockTarget(name: "FooTarget"), + MockTarget(name: "FooTarget") ], products: [ - MockProduct(name: "FooProduct", modules: ["FooTarget"]), + MockProduct(name: "FooProduct", modules: ["FooTarget"]) ], versions: ["1.0.0"] ), @@ -14782,9 +15245,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' - """), + diagnostic: .contains( + """ + multiple similar targets 'FooTarget' appear in registry package 'org.foo' and source control package 'foo' + """ + ), severity: .error ) } @@ -14800,9 +15265,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. - """), + diagnostic: .contains( + """ + dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. + """ + ), severity: .warning ) } @@ -14830,9 +15297,11 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: .contains(""" - dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. - """), + diagnostic: .contains( + """ + dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. + """ + ), severity: .warning ) } @@ -14850,7 +15319,7 @@ final class WorkspaceTests: XCTestCase { .check( dependency: "org.foo", at: .checkout(.branch("experiment")) - ) // we cannot swizzle branch based deps + ) // we cannot swizzle branch based deps result.check(dependency: "org.bar", at: .registryDownload("1.0.0")) } } @@ -14902,31 +15371,31 @@ final class WorkspaceTests: XCTestCase { MockTarget(name: "BarTests", dependencies: ["Bar"], type: .test), ], products: [ - MockProduct(name: "Foo", modules: ["Foo", "Bar"]), + MockProduct(name: "Foo", modules: ["Foo", "Bar"]) ], dependencies: [ - .sourceControl(url: bazURL, requirement: .upToNextMajor(from: "1.0.0")), + .sourceControl(url: bazURL, requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Baz", url: bazURL.absoluteString, targets: [ - MockTarget(name: "Baz"), + MockTarget(name: "Baz") ], products: [ - MockProduct(name: "Baz", modules: ["Baz"]), + MockProduct(name: "Baz", modules: ["Baz"]) ], versions: ["1.0.0"] - ), + ) ], customPackageContainerProvider: MockPackageContainerProvider(containers: [fooContainer, bazContainer]) ) let deps: [MockDependency] = [ - .sourceControl(url: bazURL, requirement: .exact("1.0.0")), + .sourceControl(url: bazURL, requirement: .exact("1.0.0")) ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in PackageGraphTesterXCTest(graph) { result in @@ -14966,27 +15435,27 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] - ), + ) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", identity: "org.foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ], registryClient: registryClient ) @@ -14995,7 +15464,7 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check(diagnostic: .equal("no registry configured for 'org' scope"), severity: .error) } - } + } } func testRegistryReleasesServerErrors() async throws { @@ -15012,27 +15481,27 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] - ), + ) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", identity: "org.foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ] ) @@ -15097,27 +15566,27 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] - ), + ) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", identity: "org.foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ] ) @@ -15184,27 +15653,27 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] - ), + ) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", identity: "org.foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ] ) @@ -15271,27 +15740,27 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] - ), + ) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", identity: "org.foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ] ) @@ -15367,27 +15836,27 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] - ), + ) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", identity: "org.foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ], registryClient: registryClient ) @@ -15435,17 +15904,17 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] - ), + ) ], products: [ - MockProduct(name: "MyProduct", modules: ["MyTarget"]), + MockProduct(name: "MyProduct", modules: ["MyTarget"]) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], registryClient: registryClient ) @@ -15463,10 +15932,10 @@ final class WorkspaceTests: XCTestCase { packageLocation: "org.foo", toolsVersion: .current, products: [ - .init(name: "Foo", type: .library(.automatic), targets: ["Foo"]), + .init(name: "Foo", type: .library(.automatic), targets: ["Foo"]) ], targets: [ - .init(name: "Foo"), + .init(name: "Foo") ] ) @@ -15513,27 +15982,27 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] - ), + ) ], dependencies: [ - .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), + .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")) ] - ), + ) ], packages: [ MockPackage( name: "Foo", identity: "org.foo", targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0"] - ), + ) ], registryClient: registryClient, defaultRegistry: .init( @@ -15570,24 +16039,24 @@ final class WorkspaceTests: XCTestCase { MockTarget( name: "MyTarget1", dependencies: [ - .product(name: "Foo", package: "org.foo"), + .product(name: "Foo", package: "org.foo") ] ), MockTarget( name: "MyTarget2", dependencies: [ - .product(name: "Bar", package: "org.bar"), + .product(name: "Bar", package: "org.bar") ] ), ], products: [ - MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]), + MockProduct(name: "MyProduct", modules: ["MyTarget1", "MyTarget2"]) ], dependencies: [ .registry(identity: "org.foo", requirement: .upToNextMajor(from: "1.0.0")), .registry(identity: "org.bar", requirement: .upToNextMajor(from: "2.0.0")), ] - ), + ) ], packages: [ MockPackage( @@ -15595,10 +16064,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.foo", metadata: metadata["org.foo"], targets: [ - MockTarget(name: "Foo"), + MockTarget(name: "Foo") ], products: [ - MockProduct(name: "Foo", modules: ["Foo"]), + MockProduct(name: "Foo", modules: ["Foo"]) ], versions: ["1.0.0", "1.1.0", "1.2.0", "1.3.0", "1.4.0", "1.5.0", "1.5.1"] ), @@ -15607,10 +16076,10 @@ final class WorkspaceTests: XCTestCase { identity: "org.bar", metadata: metadata["org.bar"], targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["2.0.0", "2.1.0", "2.2.0"] ), @@ -15618,10 +16087,10 @@ final class WorkspaceTests: XCTestCase { name: "BarMirror", url: "https://scm.com/org/bar-mirror", targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["2.0.0", "2.1.0", "2.2.0"] ), @@ -15630,10 +16099,10 @@ final class WorkspaceTests: XCTestCase { identity: "ecorp.bar", metadata: metadata["ecorp.bar"], targets: [ - MockTarget(name: "Bar"), + MockTarget(name: "Bar") ], products: [ - MockProduct(name: "Bar", modules: ["Bar"]), + MockProduct(name: "Bar", modules: ["Bar"]) ], versions: ["2.0.0", "2.1.0", "2.2.0"] ), @@ -15654,9 +16123,12 @@ final class WorkspaceTests: XCTestCase { let workspace = try await createBasicRegistryWorkspace(metadata: ["org.bar": actualMetadata]) - try await workspace.checkPackageGraph(roots: ["MyPackage"], expectedSigningEntities: [ - PackageIdentity.plain("org.bar"): XCTUnwrap(actualMetadata.signature?.signedBy), - ]) { _, diagnostics in + try await workspace.checkPackageGraph( + roots: ["MyPackage"], + expectedSigningEntities: [ + PackageIdentity.plain("org.bar"): XCTUnwrap(actualMetadata.signature?.signedBy) + ] + ) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) } } @@ -15680,9 +16152,12 @@ final class WorkspaceTests: XCTestCase { let workspace = try await createBasicRegistryWorkspace(metadata: ["org.bar": actualMetadata]) do { - try await workspace.checkPackageGraph(roots: ["MyPackage"], expectedSigningEntities: [ - PackageIdentity.plain("org.bar"): expectedSigningEntity, - ]) { _, _ in } + try await workspace.checkPackageGraph( + roots: ["MyPackage"], + expectedSigningEntities: [ + PackageIdentity.plain("org.bar"): expectedSigningEntity + ] + ) { _, _ in } XCTFail("should not succeed") } catch Workspace.SigningError.mismatchedSigningEntity(_, let expected, let actual) { XCTAssertEqual(actual, actualMetadata.signature?.signedBy) @@ -15703,9 +16178,12 @@ final class WorkspaceTests: XCTestCase { let workspace = try await createBasicRegistryWorkspace(metadata: [:]) do { - try await workspace.checkPackageGraph(roots: ["MyPackage"], expectedSigningEntities: [ - PackageIdentity.plain("org.bar"): expectedSigningEntity, - ]) { _, _ in } + try await workspace.checkPackageGraph( + roots: ["MyPackage"], + expectedSigningEntities: [ + PackageIdentity.plain("org.bar"): expectedSigningEntity + ] + ) { _, _ in } XCTFail("should not succeed") } catch Workspace.SigningError.unsigned(_, let expected) { XCTAssertEqual(expected, expectedSigningEntity) @@ -15725,9 +16203,12 @@ final class WorkspaceTests: XCTestCase { let workspace = try await createBasicRegistryWorkspace(metadata: [:]) do { - try await workspace.checkPackageGraph(roots: ["MyPackage"], expectedSigningEntities: [ - PackageIdentity.plain("foo.bar"): expectedSigningEntity, - ]) { _, _ in } + try await workspace.checkPackageGraph( + roots: ["MyPackage"], + expectedSigningEntities: [ + PackageIdentity.plain("foo.bar"): expectedSigningEntity + ] + ) { _, _ in } XCTFail("should not succeed") } catch Workspace.SigningError.expectedIdentityNotFound(let package) { XCTAssertEqual(package.description, "foo.bar") @@ -15754,9 +16235,12 @@ final class WorkspaceTests: XCTestCase { mirrors: mirrors ) - try await workspace.checkPackageGraph(roots: ["MyPackage"], expectedSigningEntities: [ - PackageIdentity.plain("org.bar"): XCTUnwrap(actualMetadata.signature?.signedBy), - ]) { graph, diagnostics in + try await workspace.checkPackageGraph( + roots: ["MyPackage"], + expectedSigningEntities: [ + PackageIdentity.plain("org.bar"): XCTUnwrap(actualMetadata.signature?.signedBy) + ] + ) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) PackageGraphTesterXCTest(graph) { result in XCTAssertNotNil(result.find(package: "ecorp.bar"), "missing package") @@ -15790,9 +16274,12 @@ final class WorkspaceTests: XCTestCase { ) do { - try await workspace.checkPackageGraph(roots: ["MyPackage"], expectedSigningEntities: [ - PackageIdentity.plain("org.bar"): expectedSigningEntity, - ]) { _, _ in } + try await workspace.checkPackageGraph( + roots: ["MyPackage"], + expectedSigningEntities: [ + PackageIdentity.plain("org.bar"): expectedSigningEntity + ] + ) { _, _ in } XCTFail("should not succeed") } catch Workspace.SigningError.mismatchedSigningEntity(_, let expected, let actual) { XCTAssertEqual(actual, actualMetadata.signature?.signedBy) @@ -15816,9 +16303,12 @@ final class WorkspaceTests: XCTestCase { let workspace = try await createBasicRegistryWorkspace(metadata: [:], mirrors: mirrors) do { - try await workspace.checkPackageGraph(roots: ["MyPackage"], expectedSigningEntities: [ - PackageIdentity.plain("org.bar"): expectedSigningEntity, - ]) { _, _ in } + try await workspace.checkPackageGraph( + roots: ["MyPackage"], + expectedSigningEntities: [ + PackageIdentity.plain("org.bar"): expectedSigningEntity + ] + ) { _, _ in } XCTFail("should not succeed") } catch Workspace.SigningError.unsigned(_, let expected) { XCTAssertEqual(expected, expectedSigningEntity) @@ -15841,9 +16331,12 @@ final class WorkspaceTests: XCTestCase { let workspace = try await createBasicRegistryWorkspace(metadata: [:], mirrors: mirrors) do { - try await workspace.checkPackageGraph(roots: ["MyPackage"], expectedSigningEntities: [ - PackageIdentity.plain("org.bar"): expectedSigningEntity, - ]) { _, _ in } + try await workspace.checkPackageGraph( + roots: ["MyPackage"], + expectedSigningEntities: [ + PackageIdentity.plain("org.bar"): expectedSigningEntity + ] + ) { _, _ in } XCTFail("should not succeed") } catch Workspace.SigningError.expectedSignedMirroredToSourceControl(_, let expected) { XCTAssertEqual(expected, expectedSigningEntity) @@ -15876,112 +16369,120 @@ final class WorkspaceTests: XCTestCase { throw StringError("Invalid package identifier: '\(packageIdentity)'") } - let configuration = configuration ?? { - var configuration = PackageRegistry.RegistryConfiguration() - configuration.defaultRegistry = .init(url: "http://localhost", supportsAvailability: false) - configuration.security = .testDefault - return configuration - }() + let configuration = + configuration + ?? { + var configuration = PackageRegistry.RegistryConfiguration() + configuration.defaultRegistry = .init(url: "http://localhost", supportsAvailability: false) + configuration.security = .testDefault + return configuration + }() - let releasesRequestHandler = releasesRequestHandler ?? { _, _ in - let metadata = RegistryClient.Serialization.PackageMetadata( - releases: [packageVersion.description: .init(url: .none, problem: .none)] - ) - return HTTPClientResponse( - statusCode: 200, - headers: [ - "Content-Version": "1", - "Content-Type": "application/json", - ], - body: try! jsonEncoder.encode(metadata) - ) - } + let releasesRequestHandler = + releasesRequestHandler ?? { _, _ in + let metadata = RegistryClient.Serialization.PackageMetadata( + releases: [packageVersion.description: .init(url: .none, problem: .none)] + ) + return HTTPClientResponse( + statusCode: 200, + headers: [ + "Content-Version": "1", + "Content-Type": "application/json", + ], + body: try! jsonEncoder.encode(metadata) + ) + } - let versionMetadataRequestHandler = versionMetadataRequestHandler ?? { _, _ in - let metadata = RegistryClient.Serialization.VersionMetadata( - id: packageIdentity.description, - version: packageVersion.description, - resources: [ - .init( - name: "source-archive", - type: "application/zip", - checksum: "", - signing: nil + let versionMetadataRequestHandler = + versionMetadataRequestHandler ?? { _, _ in + let metadata = RegistryClient.Serialization.VersionMetadata( + id: packageIdentity.description, + version: packageVersion.description, + resources: [ + .init( + name: "source-archive", + type: "application/zip", + checksum: "", + signing: nil + ) + ], + metadata: .init( + description: "package \(identity) description", + licenseURL: "/\(identity)/license", + readmeURL: "/\(identity)/readme" ), - ], - metadata: .init( - description: "package \(identity) description", - licenseURL: "/\(identity)/license", - readmeURL: "/\(identity)/readme" - ), - publishedAt: nil - ) - return HTTPClientResponse( - statusCode: 200, - headers: [ - "Content-Version": "1", - "Content-Type": "application/json", - ], - body: try! jsonEncoder.encode(metadata) - ) - } - - let manifestRequestHandler = manifestRequestHandler ?? { _, _ in - HTTPClientResponse( - statusCode: 200, - headers: [ - "Content-Version": "1", - "Content-Type": "text/x-swift", - ], - body: Data("// swift-tools-version:\(ToolsVersion.current)".utf8) - ) - } + publishedAt: nil + ) + return HTTPClientResponse( + statusCode: 200, + headers: [ + "Content-Version": "1", + "Content-Type": "application/json", + ], + body: try! jsonEncoder.encode(metadata) + ) + } - let downloadArchiveRequestHandler = downloadArchiveRequestHandler ?? { request, _ in - switch request.kind { - case .download(let fileSystem, let destination): - // creates a dummy zipfile which is required by the archiver step - try! fileSystem.createDirectory(destination.parentDirectory, recursive: true) - try! fileSystem.writeFileContents(destination, string: "") - default: - preconditionFailure("invalid request") + let manifestRequestHandler = + manifestRequestHandler ?? { _, _ in + HTTPClientResponse( + statusCode: 200, + headers: [ + "Content-Version": "1", + "Content-Type": "text/x-swift", + ], + body: Data("// swift-tools-version:\(ToolsVersion.current)".utf8) + ) } - return HTTPClientResponse( - statusCode: 200, - headers: [ - "Content-Version": "1", - "Content-Type": "application/zip", - ], - body: Data("".utf8) - ) - } + let downloadArchiveRequestHandler = + downloadArchiveRequestHandler ?? { request, _ in + switch request.kind { + case .download(let fileSystem, let destination): + // creates a dummy zipfile which is required by the archiver step + try! fileSystem.createDirectory(destination.parentDirectory, recursive: true) + try! fileSystem.writeFileContents(destination, string: "") + default: + preconditionFailure("invalid request") + } - let archiver = archiver ?? MockArchiver(handler: { _, _, to, completion in - do { - let packagePath = to.appending("top") - try fileSystem.createDirectory(packagePath, recursive: true) - try fileSystem.writeFileContents(packagePath.appending(component: Manifest.filename), bytes: []) - try ToolsVersionSpecificationWriter.rewriteSpecification( - manifestDirectory: packagePath, - toolsVersion: .current, - fileSystem: fileSystem - ) - for target in targets { - try fileSystem.createDirectory( - packagePath.appending(components: "Sources", target), - recursive: true - ) - try fileSystem.writeFileContents( - packagePath.appending(components: ["Sources", target, "file.swift"]), - bytes: [] + return HTTPClientResponse( + statusCode: 200, + headers: [ + "Content-Version": "1", + "Content-Type": "application/zip", + ], + body: Data("".utf8) + ) + } + + let archiver = + archiver + ?? MockArchiver(handler: { _, _, to, completion in + do { + let packagePath = to.appending("top") + try fileSystem.createDirectory(packagePath, recursive: true) + try fileSystem.writeFileContents(packagePath.appending(component: Manifest.filename), bytes: []) + try ToolsVersionSpecificationWriter.rewriteSpecification( + manifestDirectory: packagePath, + toolsVersion: .current, + fileSystem: fileSystem ) + for target in targets { + try fileSystem.createDirectory( + packagePath.appending(components: "Sources", target), + recursive: true + ) + try fileSystem.writeFileContents( + packagePath.appending(components: ["Sources", target, "file.swift"]), + bytes: [] + ) + } + completion(.success(())) + } catch { + completion(.failure(error)) } - completion(.success(())) - } catch { - completion(.failure(error)) - } - }) + }) let fingerprintStorage = fingerprintStorage ?? MockPackageFingerprintStorage() let signingEntityStorage = signingEntityStorage ?? MockPackageSigningEntityStorage() @@ -15993,24 +16494,27 @@ final class WorkspaceTests: XCTestCase { signingEntityStorage: signingEntityStorage, signingEntityCheckingMode: signingEntityCheckingMode, authorizationProvider: authorizationProvider, - customHTTPClient: HTTPClient(configuration: .init(), implementation: { request, progress in - switch request.url.path { - // request to get package releases - case "/\(identity.scope)/\(identity.name)": - return try await releasesRequestHandler(request, progress) - // request to get package version metadata - case "/\(identity.scope)/\(identity.name)/\(packageVersion)": - return try await versionMetadataRequestHandler(request, progress) - // request to get package manifest - case "/\(identity.scope)/\(identity.name)/\(packageVersion)/Package.swift": - return try await manifestRequestHandler(request, progress) - // request to get download the version source archive - case "/\(identity.scope)/\(identity.name)/\(packageVersion).zip": - return try await downloadArchiveRequestHandler(request, progress) - default: - throw StringError("unexpected url \(request.url)") + customHTTPClient: HTTPClient( + configuration: .init(), + implementation: { request, progress in + switch request.url.path { + // request to get package releases + case "/\(identity.scope)/\(identity.name)": + return try await releasesRequestHandler(request, progress) + // request to get package version metadata + case "/\(identity.scope)/\(identity.name)/\(packageVersion)": + return try await versionMetadataRequestHandler(request, progress) + // request to get package manifest + case "/\(identity.scope)/\(identity.name)/\(packageVersion)/Package.swift": + return try await manifestRequestHandler(request, progress) + // request to get download the version source archive + case "/\(identity.scope)/\(identity.name)/\(packageVersion).zip": + return try await downloadArchiveRequestHandler(request, progress) + default: + throw StringError("unexpected url \(request.url)") + } } - }), + ), customArchiverProvider: { _ in archiver }, delegate: .none, checksumAlgorithm: MockHashAlgorithm() @@ -16024,19 +16528,19 @@ func createDummyXCFramework(fileSystem: FileSystem, path: AbsolutePath, name: St try fileSystem.writeFileContents( path.appending("info.plist"), string: """ - - - - - AvailableLibraries - - CFBundlePackageType - XFWK - XCFrameworkFormatVersion - 1.0 - - - """ + + + + + AvailableLibraries + + CFBundlePackageType + XFWK + XCFrameworkFormatVersion + 1.0 + + + """ ) } @@ -16046,11 +16550,11 @@ func createDummyArtifactBundle(fileSystem: FileSystem, path: AbsolutePath, name: try fileSystem.writeFileContents( path.appending("info.json"), string: """ - { - "schemaVersion": "1.0", - "artifacts": {} - } - """ + { + "schemaVersion": "1.0", + "artifacts": {} + } + """ ) } diff --git a/Tests/XCBuildSupportTests/PIFBuilderTests.swift b/Tests/XCBuildSupportTests/PIFBuilderTests.swift index d3ca5fc8bbe..22b2712c79c 100644 --- a/Tests/XCBuildSupportTests/PIFBuilderTests.swift +++ b/Tests/XCBuildSupportTests/PIFBuilderTests.swift @@ -13,8 +13,7 @@ import Basics import Foundation -@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) -import PackageGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph import PackageLoading @testable import PackageModel @@ -30,13 +29,13 @@ final class PIFBuilderTests: XCTestCase { func testOrdering() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif // Repeat multiple times to detect non-deterministic shuffling due to sets. - for _ in 0 ..< 10 { + for _ in 0..<10 { let fs = InMemoryFileSystem( emptyFiles: - "/A/Sources/A1/main.swift", + "/A/Sources/A1/main.swift", "/A/Sources/A2/lib.swift", "/A/Sources/A3/lib.swift", "/B/Sources/B1/main.swift", @@ -65,7 +64,7 @@ final class PIFBuilderTests: XCTestCase { path: "/A", toolsVersion: .v5_2, dependencies: [ - .localSourceControl(path: "/B", requirement: .branch("master")), + .localSourceControl(path: "/B", requirement: .branch("master")) ], products: [ .init(name: "alib", type: .library(.static), targets: ["A2"]), @@ -105,23 +104,23 @@ final class PIFBuilderTests: XCTestCase { ) let projectBTargetNames = pif.workspace.projects[1].targets.map(\.name) #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - XCTAssertEqual(projectBTargetNames, ["blib_7AE74026D_PackageProduct", "B2"]) + XCTAssertEqual(projectBTargetNames, ["blib_7AE74026D_PackageProduct", "B2"]) #else - XCTAssertEqual( - projectBTargetNames, - ["bexe_7ADFD1428_PackageProduct", "blib_7AE74026D_PackageProduct", "B2"] - ) + XCTAssertEqual( + projectBTargetNames, + ["bexe_7ADFD1428_PackageProduct", "blib_7AE74026D_PackageProduct", "B2"] + ) #endif } } func testProject() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/main.swift", + "/Foo/Sources/foo/main.swift", "/Foo/Tests/FooTests/tests.swift", "/Bar/Sources/BarLib/lib.swift" ) @@ -138,7 +137,7 @@ final class PIFBuilderTests: XCTestCase { defaultLocalization: "fr", toolsVersion: .v5_2, dependencies: [ - .localSourceControl(path: "/Bar", requirement: .branch("master")), + .localSourceControl(path: "/Bar", requirement: .branch("master")) ], targets: [ .init(name: "foo", dependencies: [.product(name: "BarLib", package: "Bar")]), @@ -156,7 +155,7 @@ final class PIFBuilderTests: XCTestCase { ], toolsVersion: .v5_2, products: [ - .init(name: "BarLib", type: .library(.automatic), targets: ["BarLib"]), + .init(name: "BarLib", type: .library(.automatic), targets: ["BarLib"]) ], targets: [ .init(name: "BarLib"), @@ -422,11 +421,11 @@ final class PIFBuilderTests: XCTestCase { func testExecutableProducts() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/main.swift", + "/Foo/Sources/foo/main.swift", "/Foo/Sources/cfoo/main.c", "/Foo/Sources/FooLib/lib.swift", "/Foo/Sources/SystemLib/module.modulemap", @@ -445,21 +444,27 @@ final class PIFBuilderTests: XCTestCase { toolsVersion: .v5_2, swiftLanguageVersions: [.v4_2, .v5], dependencies: [ - .localSourceControl(path: "/Bar", requirement: .branch("master")), + .localSourceControl(path: "/Bar", requirement: .branch("master")) ], targets: [ - .init(name: "foo", dependencies: [ - "FooLib", - "SystemLib", - "cfoo", - .product(name: "bar", package: "Bar"), - .product(name: "cbar", package: "Bar"), - ]), + .init( + name: "foo", + dependencies: [ + "FooLib", + "SystemLib", + "cfoo", + .product(name: "bar", package: "Bar"), + .product(name: "cbar", package: "Bar"), + ] + ), .init(name: "cfoo"), .init(name: "SystemLib", type: .system, pkgConfig: "Foo"), - .init(name: "FooLib", dependencies: [ - .product(name: "BarLib", package: "Bar"), - ]), + .init( + name: "FooLib", + dependencies: [ + .product(name: "BarLib", package: "Bar") + ] + ), ] ), Manifest.createLocalSourceControlManifest( @@ -506,21 +511,27 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.name, "foo_1EF26F7F_PackageProduct") XCTAssertEqual(target.productType, .executable) XCTAssertEqual(target.productName, "foo") - XCTAssertEqual(target.dependencies, [ - "PACKAGE-PRODUCT:cfoo", - "PACKAGE-PRODUCT:bar", - "PACKAGE-PRODUCT:BarLib", - "PACKAGE-PRODUCT:cbar", - "PACKAGE-TARGET:FooLib", - "PACKAGE-TARGET:SystemLib", - ]) + XCTAssertEqual( + target.dependencies, + [ + "PACKAGE-PRODUCT:cfoo", + "PACKAGE-PRODUCT:bar", + "PACKAGE-PRODUCT:BarLib", + "PACKAGE-PRODUCT:cbar", + "PACKAGE-TARGET:FooLib", + "PACKAGE-TARGET:SystemLib", + ] + ) XCTAssertEqual(target.sources, ["/Foo/Sources/foo/main.swift"]) - XCTAssertEqual(target.frameworks, [ - "PACKAGE-TARGET:FooLib", - "PACKAGE-PRODUCT:BarLib", - "PACKAGE-PRODUCT:cbar", - "PACKAGE-PRODUCT:bar", - ]) + XCTAssertEqual( + target.frameworks, + [ + "PACKAGE-TARGET:FooLib", + "PACKAGE-PRODUCT:BarLib", + "PACKAGE-PRODUCT:cbar", + "PACKAGE-PRODUCT:bar", + ] + ) target.checkBuildConfiguration("Debug") { configuration in XCTAssertEqual(configuration.guid, "PACKAGE-PRODUCT:foo::BUILDCONFIG_Debug") @@ -780,11 +791,11 @@ final class PIFBuilderTests: XCTestCase { func testTestProducts() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/FooTests/FooTests.swift", + "/Foo/Sources/FooTests/FooTests.swift", "/Foo/Sources/CFooTests/CFooTests.m", "/Foo/Sources/foo/main.swift", "/Foo/Sources/FooLib/lib.swift", @@ -806,21 +817,28 @@ final class PIFBuilderTests: XCTestCase { toolsVersion: .v5_2, swiftLanguageVersions: [.v4_2, .v5], dependencies: [ - .localSourceControl(path: "/Bar", requirement: .branch("master")), + .localSourceControl(path: "/Bar", requirement: .branch("master")) ], targets: [ - .init(name: "FooTests", dependencies: [ - "foo", - "FooLib", - .product(name: "bar", package: "Bar"), - "SystemLib", - ], type: .test), + .init( + name: "FooTests", + dependencies: [ + "foo", + "FooLib", + .product(name: "bar", package: "Bar"), + "SystemLib", + ], + type: .test + ), .init(name: "CFooTests", type: .test), .init(name: "foo"), .init(name: "SystemLib", type: .system, pkgConfig: "Foo"), - .init(name: "FooLib", dependencies: [ - .product(name: "BarLib", package: "Bar"), - ]), + .init( + name: "FooLib", + dependencies: [ + .product(name: "BarLib", package: "Bar") + ] + ), ] ), Manifest.createLocalSourceControlManifest( @@ -865,19 +883,25 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.name, "FooTests_-5E24708DC81AF5C1_PackageProduct") XCTAssertEqual(target.productType, .unitTest) XCTAssertEqual(target.productName, "FooTests") - XCTAssertEqual(target.dependencies, [ - "PACKAGE-PRODUCT:foo", - "PACKAGE-PRODUCT:bar", - "PACKAGE-PRODUCT:BarLib", - "PACKAGE-TARGET:FooLib", - "PACKAGE-TARGET:SystemLib", - ]) + XCTAssertEqual( + target.dependencies, + [ + "PACKAGE-PRODUCT:foo", + "PACKAGE-PRODUCT:bar", + "PACKAGE-PRODUCT:BarLib", + "PACKAGE-TARGET:FooLib", + "PACKAGE-TARGET:SystemLib", + ] + ) XCTAssertEqual(target.sources, ["/Foo/Sources/FooTests/FooTests.swift"]) - XCTAssertEqual(target.frameworks, [ - "PACKAGE-PRODUCT:bar", - "PACKAGE-TARGET:FooLib", - "PACKAGE-PRODUCT:BarLib", - ]) + XCTAssertEqual( + target.frameworks, + [ + "PACKAGE-PRODUCT:bar", + "PACKAGE-TARGET:FooLib", + "PACKAGE-PRODUCT:BarLib", + ] + ) target.checkBuildConfiguration("Debug") { configuration in XCTAssertEqual(configuration.guid, "PACKAGE-PRODUCT:FooTests::BUILDCONFIG_Debug") @@ -886,15 +910,21 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(settings[.CLANG_ENABLE_MODULES], "YES") XCTAssertEqual(settings[.DEFINES_MODULE], "YES") XCTAssertEqual(settings[.GENERATE_INFOPLIST_FILE], "YES") - XCTAssertEqual(settings[.LD_RUNPATH_SEARCH_PATHS], [ - "$(inherited)", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", - ]) - XCTAssertEqual(settings[.LIBRARY_SEARCH_PATHS], [ - "$(inherited)", - "/toolchain/lib/swift/macosx", - ]) + XCTAssertEqual( + settings[.LD_RUNPATH_SEARCH_PATHS], + [ + "$(inherited)", + "@loader_path/Frameworks", + "@loader_path/../Frameworks", + ] + ) + XCTAssertEqual( + settings[.LIBRARY_SEARCH_PATHS], + [ + "$(inherited)", + "/toolchain/lib/swift/macosx", + ] + ) XCTAssertEqual( settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS], ["$(inherited)", "SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE"] @@ -937,15 +967,21 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(settings[.CLANG_ENABLE_MODULES], "YES") XCTAssertEqual(settings[.DEFINES_MODULE], "YES") XCTAssertEqual(settings[.GENERATE_INFOPLIST_FILE], "YES") - XCTAssertEqual(settings[.LD_RUNPATH_SEARCH_PATHS], [ - "$(inherited)", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", - ]) - XCTAssertEqual(settings[.LIBRARY_SEARCH_PATHS], [ - "$(inherited)", - "/toolchain/lib/swift/macosx", - ]) + XCTAssertEqual( + settings[.LD_RUNPATH_SEARCH_PATHS], + [ + "$(inherited)", + "@loader_path/Frameworks", + "@loader_path/../Frameworks", + ] + ) + XCTAssertEqual( + settings[.LIBRARY_SEARCH_PATHS], + [ + "$(inherited)", + "/toolchain/lib/swift/macosx", + ] + ) XCTAssertEqual( settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS], ["$(inherited)", "SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE"] @@ -999,19 +1035,28 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(settings[.CLANG_ENABLE_MODULES], "YES") XCTAssertEqual(settings[.DEFINES_MODULE], "YES") XCTAssertEqual(settings[.GENERATE_INFOPLIST_FILE], "YES") - XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], [ - "$(inherited)", - "/Foo/Sources/CFooTests/include", - ]) - XCTAssertEqual(settings[.LD_RUNPATH_SEARCH_PATHS], [ - "$(inherited)", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", - ]) - XCTAssertEqual(settings[.LIBRARY_SEARCH_PATHS], [ - "$(inherited)", - "/toolchain/lib/swift/macosx", - ]) + XCTAssertEqual( + settings[.HEADER_SEARCH_PATHS], + [ + "$(inherited)", + "/Foo/Sources/CFooTests/include", + ] + ) + XCTAssertEqual( + settings[.LD_RUNPATH_SEARCH_PATHS], + [ + "$(inherited)", + "@loader_path/Frameworks", + "@loader_path/../Frameworks", + ] + ) + XCTAssertEqual( + settings[.LIBRARY_SEARCH_PATHS], + [ + "$(inherited)", + "/toolchain/lib/swift/macosx", + ] + ) XCTAssertEqual(settings[.PACKAGE_RESOURCE_TARGET_KIND], "regular") XCTAssertEqual(settings[.PRODUCT_BUNDLE_IDENTIFIER], "CFooTests") XCTAssertEqual(settings[.PRODUCT_MODULE_NAME], "CFooTests") @@ -1049,19 +1094,28 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(settings[.CLANG_ENABLE_MODULES], "YES") XCTAssertEqual(settings[.DEFINES_MODULE], "YES") XCTAssertEqual(settings[.GENERATE_INFOPLIST_FILE], "YES") - XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], [ - "$(inherited)", - "/Foo/Sources/CFooTests/include", - ]) - XCTAssertEqual(settings[.LD_RUNPATH_SEARCH_PATHS], [ - "$(inherited)", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", - ]) - XCTAssertEqual(settings[.LIBRARY_SEARCH_PATHS], [ - "$(inherited)", - "/toolchain/lib/swift/macosx", - ]) + XCTAssertEqual( + settings[.HEADER_SEARCH_PATHS], + [ + "$(inherited)", + "/Foo/Sources/CFooTests/include", + ] + ) + XCTAssertEqual( + settings[.LD_RUNPATH_SEARCH_PATHS], + [ + "$(inherited)", + "@loader_path/Frameworks", + "@loader_path/../Frameworks", + ] + ) + XCTAssertEqual( + settings[.LIBRARY_SEARCH_PATHS], + [ + "$(inherited)", + "/toolchain/lib/swift/macosx", + ] + ) XCTAssertEqual(settings[.PACKAGE_RESOURCE_TARGET_KIND], "regular") XCTAssertEqual(settings[.PRODUCT_BUNDLE_IDENTIFIER], "CFooTests") XCTAssertEqual(settings[.PRODUCT_MODULE_NAME], "CFooTests") @@ -1105,11 +1159,11 @@ final class PIFBuilderTests: XCTestCase { func testLibraryProducts() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/FooLib1/lib.swift", + "/Foo/Sources/FooLib1/lib.swift", "/Foo/Sources/FooLib2/lib.swift", "/Foo/Sources/SystemLib/module.modulemap", "/Bar/Sources/BarLib/lib.swift" @@ -1125,7 +1179,7 @@ final class PIFBuilderTests: XCTestCase { toolsVersion: .v5_2, swiftLanguageVersions: [.v4_2, .v5], dependencies: [ - .localSourceControl(path: "/Bar", requirement: .branch("master")), + .localSourceControl(path: "/Bar", requirement: .branch("master")) ], products: [ .init(name: "FooLib1", type: .library(.static), targets: ["FooLib1"]), @@ -1133,9 +1187,12 @@ final class PIFBuilderTests: XCTestCase { ], targets: [ .init(name: "FooLib1", dependencies: ["SystemLib", "FooLib2"]), - .init(name: "FooLib2", dependencies: [ - .product(name: "BarLib", package: "Bar"), - ]), + .init( + name: "FooLib2", + dependencies: [ + .product(name: "BarLib", package: "Bar") + ] + ), .init(name: "SystemLib", type: .system, pkgConfig: "Foo"), ] ), @@ -1147,10 +1204,10 @@ final class PIFBuilderTests: XCTestCase { cxxLanguageStandard: "c++14", swiftLanguageVersions: [.v4_2], products: [ - .init(name: "BarLib", type: .library(.dynamic), targets: ["BarLib"]), + .init(name: "BarLib", type: .library(.dynamic), targets: ["BarLib"]) ], targets: [ - .init(name: "BarLib"), + .init(name: "BarLib") ] ), ], @@ -1176,17 +1233,23 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.name, "FooLib1_32B0F01AD0DD0FF3_PackageProduct") XCTAssertEqual(target.productType, .packageProduct) XCTAssertEqual(target.productName, "libFooLib1.a") - XCTAssertEqual(target.dependencies, [ - "PACKAGE-TARGET:FooLib1", - "PACKAGE-TARGET:FooLib2", - "PACKAGE-PRODUCT:BarLib", - ]) + XCTAssertEqual( + target.dependencies, + [ + "PACKAGE-TARGET:FooLib1", + "PACKAGE-TARGET:FooLib2", + "PACKAGE-PRODUCT:BarLib", + ] + ) XCTAssertEqual(target.sources, []) - XCTAssertEqual(target.frameworks, [ - "PACKAGE-TARGET:FooLib1", - "PACKAGE-TARGET:FooLib2", - "PACKAGE-PRODUCT:BarLib", - ]) + XCTAssertEqual( + target.frameworks, + [ + "PACKAGE-TARGET:FooLib1", + "PACKAGE-TARGET:FooLib2", + "PACKAGE-PRODUCT:BarLib", + ] + ) target.checkBuildConfiguration("Debug") { configuration in XCTAssertEqual(configuration.guid, "PACKAGE-PRODUCT:FooLib1::BUILDCONFIG_Debug") @@ -1213,15 +1276,21 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.name, "FooLib2_32B0F01AD0DD1074_PackageProduct") XCTAssertEqual(target.productType, .packageProduct) XCTAssertEqual(target.productName, "libFooLib2.a") - XCTAssertEqual(target.dependencies, [ - "PACKAGE-TARGET:FooLib2", - "PACKAGE-PRODUCT:BarLib", - ]) + XCTAssertEqual( + target.dependencies, + [ + "PACKAGE-TARGET:FooLib2", + "PACKAGE-PRODUCT:BarLib", + ] + ) XCTAssertEqual(target.sources, []) - XCTAssertEqual(target.frameworks, [ - "PACKAGE-TARGET:FooLib2", - "PACKAGE-PRODUCT:BarLib", - ]) + XCTAssertEqual( + target.frameworks, + [ + "PACKAGE-TARGET:FooLib2", + "PACKAGE-PRODUCT:BarLib", + ] + ) target.checkBuildConfiguration("Debug") { configuration in XCTAssertEqual(configuration.guid, "PACKAGE-PRODUCT:FooLib2::BUILDCONFIG_Debug") @@ -1316,11 +1385,11 @@ final class PIFBuilderTests: XCTestCase { func testLibraryTargets() async throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/FooLib1/lib.swift", + "/Foo/Sources/FooLib1/lib.swift", "/Foo/Sources/FooLib2/lib.cpp", "/Foo/Sources/SystemLib/module.modulemap", "/Bar/Sources/BarLib/lib.c" @@ -1337,13 +1406,16 @@ final class PIFBuilderTests: XCTestCase { cxxLanguageStandard: "c++14", swiftLanguageVersions: [.v4_2, .v5], dependencies: [ - .localSourceControl(path: "/Bar", requirement: .branch("master")), + .localSourceControl(path: "/Bar", requirement: .branch("master")) ], targets: [ .init(name: "FooLib1", dependencies: ["SystemLib", "FooLib2"]), - .init(name: "FooLib2", dependencies: [ - .product(name: "BarLib", package: "Bar"), - ]), + .init( + name: "FooLib2", + dependencies: [ + .product(name: "BarLib", package: "Bar") + ] + ), .init(name: "SystemLib", type: .system, pkgConfig: "Foo"), ] ), @@ -1354,10 +1426,10 @@ final class PIFBuilderTests: XCTestCase { cLanguageStandard: "c11", swiftLanguageVersions: [.v4_2], products: [ - .init(name: "BarLib", type: .library(.dynamic), targets: ["BarLib"]), + .init(name: "BarLib", type: .library(.dynamic), targets: ["BarLib"]) ], targets: [ - .init(name: "BarLib"), + .init(name: "BarLib") ] ), ], @@ -1383,11 +1455,14 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.name, "FooLib1") XCTAssertEqual(target.productType, .objectFile) XCTAssertEqual(target.productName, "FooLib1_Module.o") - XCTAssertEqual(target.dependencies, [ - "PACKAGE-TARGET:FooLib2", - "PACKAGE-TARGET:SystemLib", - "PACKAGE-PRODUCT:BarLib", - ]) + XCTAssertEqual( + target.dependencies, + [ + "PACKAGE-TARGET:FooLib2", + "PACKAGE-TARGET:SystemLib", + "PACKAGE-PRODUCT:BarLib", + ] + ) XCTAssertEqual(target.sources, ["/Foo/Sources/FooLib1/lib.swift"]) XCTAssertEqual(target.frameworks, []) @@ -1400,12 +1475,15 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(settings[.DEFINES_MODULE], "YES") XCTAssertEqual(settings[.GENERATE_MASTER_OBJECT_FILE], "NO") XCTAssertEqual(settings[.MACH_O_TYPE], "mh_object") - XCTAssertEqual(settings[.MODULEMAP_FILE_CONTENTS], """ - module FooLib1 { - header "FooLib1-Swift.h" - export * - } - """) + XCTAssertEqual( + settings[.MODULEMAP_FILE_CONTENTS], + """ + module FooLib1 { + header "FooLib1-Swift.h" + export * + } + """ + ) XCTAssertEqual( settings[.MODULEMAP_PATH], "$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib1.modulemap" @@ -1437,12 +1515,15 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(settings[.DEFINES_MODULE], "YES") XCTAssertEqual(settings[.GENERATE_MASTER_OBJECT_FILE], "NO") XCTAssertEqual(settings[.MACH_O_TYPE], "mh_object") - XCTAssertEqual(settings[.MODULEMAP_FILE_CONTENTS], """ - module FooLib1 { - header "FooLib1-Swift.h" - export * - } - """) + XCTAssertEqual( + settings[.MODULEMAP_FILE_CONTENTS], + """ + module FooLib1 { + header "FooLib1-Swift.h" + export * + } + """ + ) XCTAssertEqual( settings[.MODULEMAP_PATH], "$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib1.modulemap" @@ -1466,10 +1547,13 @@ final class PIFBuilderTests: XCTestCase { } target.checkAllImpartedBuildSettings { settings in - XCTAssertEqual(settings[.OTHER_CFLAGS], [ - "$(inherited)", - "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib1.modulemap", - ]) + XCTAssertEqual( + settings[.OTHER_CFLAGS], + [ + "$(inherited)", + "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib1.modulemap", + ] + ) XCTAssertEqual(settings[.OTHER_LDRFLAGS], []) XCTAssertEqual(settings[.OTHER_LDFLAGS], ["$(inherited)", "-Wl,-no_warn_duplicate_libraries"]) } @@ -1497,12 +1581,15 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "/Foo/Sources/FooLib2/include"] ) XCTAssertEqual(settings[.MACH_O_TYPE], "mh_object") - XCTAssertEqual(settings[.MODULEMAP_FILE_CONTENTS], """ - module FooLib2 { - umbrella "/Foo/Sources/FooLib2/include" - export * - } - """) + XCTAssertEqual( + settings[.MODULEMAP_FILE_CONTENTS], + """ + module FooLib2 { + umbrella "/Foo/Sources/FooLib2/include" + export * + } + """ + ) XCTAssertEqual( settings[.MODULEMAP_PATH], "$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib2.modulemap" @@ -1529,12 +1616,15 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "/Foo/Sources/FooLib2/include"] ) XCTAssertEqual(settings[.MACH_O_TYPE], "mh_object") - XCTAssertEqual(settings[.MODULEMAP_FILE_CONTENTS], """ - module FooLib2 { - umbrella "/Foo/Sources/FooLib2/include" - export * - } - """) + XCTAssertEqual( + settings[.MODULEMAP_FILE_CONTENTS], + """ + module FooLib2 { + umbrella "/Foo/Sources/FooLib2/include" + export * + } + """ + ) XCTAssertEqual( settings[.MODULEMAP_PATH], "$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib2.modulemap" @@ -1549,20 +1639,26 @@ final class PIFBuilderTests: XCTestCase { target.checkAllImpartedBuildSettings { settings in XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], ["$(inherited)", "/Foo/Sources/FooLib2/include"]) - XCTAssertEqual(settings[.OTHER_CFLAGS], [ - "$(inherited)", - "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib2.modulemap", - ]) + XCTAssertEqual( + settings[.OTHER_CFLAGS], + [ + "$(inherited)", + "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib2.modulemap", + ] + ) XCTAssertEqual(settings[.OTHER_LDRFLAGS], []) XCTAssertEqual( settings[.OTHER_LDFLAGS], ["$(inherited)", "-lc++", "-Wl,-no_warn_duplicate_libraries"] ) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], [ - "$(inherited)", - "-Xcc", - "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib2.modulemap", - ]) + XCTAssertEqual( + settings[.OTHER_SWIFT_FLAGS], + [ + "$(inherited)", + "-Xcc", + "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/FooLib2.modulemap", + ] + ) } } } @@ -1590,12 +1686,15 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "/Bar/Sources/BarLib/include"] ) XCTAssertEqual(settings[.MACH_O_TYPE], "mh_object") - XCTAssertEqual(settings[.MODULEMAP_FILE_CONTENTS], """ - module BarLib { - umbrella "/Bar/Sources/BarLib/include" - export * - } - """) + XCTAssertEqual( + settings[.MODULEMAP_FILE_CONTENTS], + """ + module BarLib { + umbrella "/Bar/Sources/BarLib/include" + export * + } + """ + ) XCTAssertEqual( settings[.MODULEMAP_PATH], "$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/BarLib.modulemap" @@ -1622,12 +1721,15 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "/Bar/Sources/BarLib/include"] ) XCTAssertEqual(settings[.MACH_O_TYPE], "mh_object") - XCTAssertEqual(settings[.MODULEMAP_FILE_CONTENTS], """ - module BarLib { - umbrella "/Bar/Sources/BarLib/include" - export * - } - """) + XCTAssertEqual( + settings[.MODULEMAP_FILE_CONTENTS], + """ + module BarLib { + umbrella "/Bar/Sources/BarLib/include" + export * + } + """ + ) XCTAssertEqual( settings[.MODULEMAP_PATH], "$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/BarLib.modulemap" @@ -1642,17 +1744,23 @@ final class PIFBuilderTests: XCTestCase { target.checkAllImpartedBuildSettings { settings in XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], ["$(inherited)", "/Bar/Sources/BarLib/include"]) - XCTAssertEqual(settings[.OTHER_CFLAGS], [ - "$(inherited)", - "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/BarLib.modulemap", - ]) + XCTAssertEqual( + settings[.OTHER_CFLAGS], + [ + "$(inherited)", + "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/BarLib.modulemap", + ] + ) XCTAssertEqual(settings[.OTHER_LDRFLAGS], []) XCTAssertEqual(settings[.OTHER_LDFLAGS], ["$(inherited)", "-Wl,-no_warn_duplicate_libraries"]) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], [ - "$(inherited)", - "-Xcc", - "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/BarLib.modulemap", - ]) + XCTAssertEqual( + settings[.OTHER_SWIFT_FLAGS], + [ + "$(inherited)", + "-Xcc", + "-fmodule-map-file=$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)/BarLib.modulemap", + ] + ) } } } @@ -1661,11 +1769,11 @@ final class PIFBuilderTests: XCTestCase { func testPIFGenWithModuleAliases() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/App/Sources/App/main.swift", + "/App/Sources/App/main.swift", "/App/Sources/Logging/lib.swift", "/App/Sources/Utils/lib.swift", "/Bar/Sources/Lib/lib.swift", @@ -1680,21 +1788,24 @@ final class PIFBuilderTests: XCTestCase { displayName: "App", path: "/App", dependencies: [ - .localSourceControl(path: "/Bar", requirement: .branch("main")), + .localSourceControl(path: "/Bar", requirement: .branch("main")) ], targets: [ .init(name: "App", dependencies: ["Logging", "Utils"], type: .executable), .init(name: "Logging", dependencies: []), - .init(name: "Utils", dependencies: [ - .product(name: "BarLib", package: "Bar", moduleAliases: ["Logging": "BarLogging"]), - ]), + .init( + name: "Utils", + dependencies: [ + .product(name: "BarLib", package: "Bar", moduleAliases: ["Logging": "BarLogging"]) + ] + ), ] ), Manifest.createLocalSourceControlManifest( displayName: "Bar", path: "/Bar", products: [ - .init(name: "BarLib", type: .library(.dynamic), targets: ["Lib"]), + .init(name: "BarLib", type: .library(.dynamic), targets: ["Lib"]) ], targets: [ .init(name: "Lib", dependencies: ["Logging"]), @@ -1724,16 +1835,22 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.name, "App_1DA2DD44_PackageProduct") XCTAssertEqual(target.productType, .executable) XCTAssertEqual(target.productName, "App") - XCTAssertEqual(target.dependencies, [ - "PACKAGE-TARGET:Utils", - "PACKAGE-TARGET:Logging", - "PACKAGE-PRODUCT:BarLib", - ]) - XCTAssertEqual(target.frameworks, [ - "PACKAGE-TARGET:Utils", - "PACKAGE-TARGET:Logging", - "PACKAGE-PRODUCT:BarLib", - ]) + XCTAssertEqual( + target.dependencies, + [ + "PACKAGE-TARGET:Utils", + "PACKAGE-TARGET:Logging", + "PACKAGE-PRODUCT:BarLib", + ] + ) + XCTAssertEqual( + target.frameworks, + [ + "PACKAGE-TARGET:Utils", + "PACKAGE-TARGET:Logging", + "PACKAGE-PRODUCT:BarLib", + ] + ) target.checkBuildConfiguration("Debug") { configuration in XCTAssertEqual(configuration.guid, "PACKAGE-PRODUCT:App::BUILDCONFIG_Debug") @@ -1756,9 +1873,12 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.name, "Utils") XCTAssertEqual(target.productType, .objectFile) XCTAssertEqual(target.productName, "Utils_Module.o") - XCTAssertEqual(target.dependencies, [ - "PACKAGE-PRODUCT:BarLib", - ]) + XCTAssertEqual( + target.dependencies, + [ + "PACKAGE-PRODUCT:BarLib" + ] + ) target.checkBuildConfiguration("Debug") { configuration in XCTAssertEqual(configuration.guid, "PACKAGE-TARGET:Utils::BUILDCONFIG_Debug") @@ -1890,11 +2010,11 @@ final class PIFBuilderTests: XCTestCase { func testLibraryTargetsAsDylib() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Bar/Sources/BarLib/lib.c" + "/Bar/Sources/BarLib/lib.c" ) let observability = ObservabilitySystem.makeForTesting() @@ -1908,12 +2028,12 @@ final class PIFBuilderTests: XCTestCase { cLanguageStandard: "c11", swiftLanguageVersions: [.v4_2], products: [ - .init(name: "BarLib", type: .library(.dynamic), targets: ["BarLib"]), + .init(name: "BarLib", type: .library(.dynamic), targets: ["BarLib"]) ], targets: [ - .init(name: "BarLib"), + .init(name: "BarLib") ] - ), + ) ], observabilityScope: observability.topScope ) @@ -1944,11 +2064,11 @@ final class PIFBuilderTests: XCTestCase { func testLibraryTargetWithModuleMap() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Bar/Sources/BarLib/lib.c", + "/Bar/Sources/BarLib/lib.c", "/Bar/Sources/BarLib/module.modulemap" ) @@ -1965,12 +2085,12 @@ final class PIFBuilderTests: XCTestCase { cLanguageStandard: "c11", swiftLanguageVersions: [.v4_2], products: [ - .init(name: "BarLib", type: .library(.dynamic), targets: ["BarLib"]), + .init(name: "BarLib", type: .library(.dynamic), targets: ["BarLib"]) ], targets: [ - .init(name: "BarLib"), + .init(name: "BarLib") ] - ), + ) ], observabilityScope: observability.topScope ) @@ -2005,11 +2125,11 @@ final class PIFBuilderTests: XCTestCase { func testSystemLibraryTargets() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/SystemLib1/module.modulemap", + "/Foo/Sources/SystemLib1/module.modulemap", "/Foo/Sources/SystemLib2/module.modulemap" ) @@ -2027,7 +2147,7 @@ final class PIFBuilderTests: XCTestCase { .init(name: "SystemLib1", type: .system), .init(name: "SystemLib2", type: .system, pkgConfig: "Foo"), ] - ), + ) ], observabilityScope: observability.topScope ) @@ -2066,15 +2186,21 @@ final class PIFBuilderTests: XCTestCase { } target.checkAllImpartedBuildSettings { settings in - XCTAssertEqual(settings[.OTHER_CFLAGS], [ - "$(inherited)", - "-fmodule-map-file=/Foo/Sources/SystemLib1/module.modulemap", - ]) + XCTAssertEqual( + settings[.OTHER_CFLAGS], + [ + "$(inherited)", + "-fmodule-map-file=/Foo/Sources/SystemLib1/module.modulemap", + ] + ) XCTAssertEqual(settings[.OTHER_LDRFLAGS], []) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], [ - "$(inherited)", - "-Xcc", "-fmodule-map-file=/Foo/Sources/SystemLib1/module.modulemap", - ]) + XCTAssertEqual( + settings[.OTHER_SWIFT_FLAGS], + [ + "$(inherited)", + "-Xcc", "-fmodule-map-file=/Foo/Sources/SystemLib1/module.modulemap", + ] + ) } } @@ -2097,25 +2223,34 @@ final class PIFBuilderTests: XCTestCase { } target.checkAllImpartedBuildSettings { settings in - XCTAssertEqual(settings[.OTHER_CFLAGS], [ - "$(inherited)", - "-fmodule-map-file=/Foo/Sources/SystemLib2/module.modulemap", - "-I/path/to/inc", - "-I\(self.inputsDir)", - ]) - XCTAssertEqual(settings[.OTHER_LDFLAGS], [ - "$(inherited)", - "-L/usr/da/lib", - "-lSystemModule", - "-lok", - ]) + XCTAssertEqual( + settings[.OTHER_CFLAGS], + [ + "$(inherited)", + "-fmodule-map-file=/Foo/Sources/SystemLib2/module.modulemap", + "-I/path/to/inc", + "-I\(self.inputsDir)", + ] + ) + XCTAssertEqual( + settings[.OTHER_LDFLAGS], + [ + "$(inherited)", + "-L/usr/da/lib", + "-lSystemModule", + "-lok", + ] + ) XCTAssertEqual(settings[.OTHER_LDRFLAGS], []) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], [ - "$(inherited)", - "-Xcc", "-fmodule-map-file=/Foo/Sources/SystemLib2/module.modulemap", - "-I/path/to/inc", - "-I\(self.inputsDir)", - ]) + XCTAssertEqual( + settings[.OTHER_SWIFT_FLAGS], + [ + "$(inherited)", + "-Xcc", "-fmodule-map-file=/Foo/Sources/SystemLib2/module.modulemap", + "-I/path/to/inc", + "-I\(self.inputsDir)", + ] + ) } } } @@ -2124,11 +2259,11 @@ final class PIFBuilderTests: XCTestCase { func testBinaryTargets() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/main.swift", + "/Foo/Sources/foo/main.swift", "/Foo/Sources/FooLib/lib.swift", "/Foo/Sources/FooTests/FooTests.swift", "/Foo/BinaryLibrary.xcframework/Info.plist" @@ -2143,7 +2278,7 @@ final class PIFBuilderTests: XCTestCase { path: "/Foo", toolsVersion: .v5_3, products: [ - .init(name: "FooLib", type: .library(.automatic), targets: ["FooLib"]), + .init(name: "FooLib", type: .library(.automatic), targets: ["FooLib"]) ], targets: [ .init(name: "foo", dependencies: ["BinaryLibrary"]), @@ -2151,12 +2286,12 @@ final class PIFBuilderTests: XCTestCase { .init(name: "FooTests", dependencies: ["BinaryLibrary"], type: .test), .init(name: "BinaryLibrary", path: "BinaryLibrary.xcframework", type: .binary), ] - ), + ) ], binaryArtifacts: [ .plain("foo"): [ - "BinaryLibrary": .init(kind: .xcframework, originURL: nil, path: "/Foo/BinaryLibrary.xcframework"), - ], + "BinaryLibrary": .init(kind: .xcframework, originURL: nil, path: "/Foo/BinaryLibrary.xcframework") + ] ], shouldCreateMultipleTestProducts: true, observabilityScope: observability.topScope @@ -2195,11 +2330,11 @@ final class PIFBuilderTests: XCTestCase { func testResources() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/main.swift", + "/Foo/Sources/foo/main.swift", "/Foo/Sources/foo/Resources/Data.plist", "/Foo/Sources/foo/Resources/Database.xcdatamodel", "/Foo/Sources/foo/Resources/Assets.xcassets", @@ -2225,21 +2360,32 @@ final class PIFBuilderTests: XCTestCase { path: "/Foo", toolsVersion: .v5_9, products: [ - .init(name: "FooLib", type: .library(.automatic), targets: ["FooLib"]), + .init(name: "FooLib", type: .library(.automatic), targets: ["FooLib"]) ], targets: [ - .init(name: "foo", resources: [ - // This is intentionally specific to test that we pick up `.xcdatamodel` implicitly. - .init(rule: .process(localization: .none), path: "Resources/Data.plist"), - ], type: .executable), - .init(name: "FooLib", resources: [ - .init(rule: .process(localization: .none), path: "Resources"), - ]), - .init(name: "FooTests", resources: [ - .init(rule: .process(localization: .none), path: "Resources"), - ], type: .test), + .init( + name: "foo", + resources: [ + // This is intentionally specific to test that we pick up `.xcdatamodel` implicitly. + .init(rule: .process(localization: .none), path: "Resources/Data.plist") + ], + type: .executable + ), + .init( + name: "FooLib", + resources: [ + .init(rule: .process(localization: .none), path: "Resources") + ] + ), + .init( + name: "FooTests", + resources: [ + .init(rule: .process(localization: .none), path: "Resources") + ], + type: .test + ), ] - ), + ) ], shouldCreateMultipleTestProducts: true, useXCBuildFileRules: true, @@ -2297,12 +2443,15 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.dependencies, []) XCTAssertEqual(target.sources, []) XCTAssertEqual(target.frameworks, []) - XCTAssertEqual(target.resources, [ - "/Foo/Sources/foo/Resources/Data.plist", - "/Foo/Sources/foo/Resources/Database.xcdatamodel", - "/Foo/Sources/foo/Resources/Assets.xcassets", - "/Foo/Sources/foo/Resources/Localizable.xcstrings", - ]) + XCTAssertEqual( + target.resources, + [ + "/Foo/Sources/foo/Resources/Data.plist", + "/Foo/Sources/foo/Resources/Database.xcdatamodel", + "/Foo/Sources/foo/Resources/Assets.xcassets", + "/Foo/Sources/foo/Resources/Localizable.xcstrings", + ] + ) target.checkBuildConfiguration("Debug") { configuration in XCTAssertEqual(configuration.guid, "PACKAGE-RESOURCE:foo::BUILDCONFIG_Debug") @@ -2423,12 +2572,15 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.dependencies, []) XCTAssertEqual(target.sources, []) XCTAssertEqual(target.frameworks, []) - XCTAssertEqual(target.resources, [ - "/Foo/Sources/FooTests/Resources/Data.plist", - "/Foo/Sources/FooTests/Resources/Database.xcdatamodel", - "/Foo/Sources/FooTests/Resources/Assets.xcassets", - "/Foo/Sources/FooTests/Resources/Localizable.xcstrings", - ]) + XCTAssertEqual( + target.resources, + [ + "/Foo/Sources/FooTests/Resources/Data.plist", + "/Foo/Sources/FooTests/Resources/Database.xcdatamodel", + "/Foo/Sources/FooTests/Resources/Assets.xcassets", + "/Foo/Sources/FooTests/Resources/Localizable.xcstrings", + ] + ) target.checkBuildConfiguration("Debug") { configuration in XCTAssertEqual(configuration.guid, "PACKAGE-RESOURCE:FooTests::BUILDCONFIG_Debug") @@ -2462,11 +2614,11 @@ final class PIFBuilderTests: XCTestCase { func buildSettingsTestCase(isPackageAccessModifierSupported: Bool) throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/main.swift", + "/Foo/Sources/foo/main.swift", "/Foo/Sources/FooLib/lib.swift", "/Foo/Sources/FooTests/FooTests.swift" ) @@ -2482,7 +2634,7 @@ final class PIFBuilderTests: XCTestCase { path: "/Foo", toolsVersion: toolsVersion, products: [ - .init(name: "FooLib", type: .library(.automatic), targets: ["FooLib"]), + .init(name: "FooLib", type: .library(.automatic), targets: ["FooLib"]) ], targets: [ .init( @@ -2510,50 +2662,57 @@ final class PIFBuilderTests: XCTestCase { ), ] ), - .init(name: "FooLib", settings: [ - .init( - tool: .c, - kind: .define("ENABLE_BEST_MODE") - ), - .init( - tool: .cxx, - kind: .headerSearchPath("some/path"), - condition: .init(platformNames: ["macos"]) - ), - .init( - tool: .linker, - kind: .linkedLibrary("z"), - condition: .init(config: "debug") - ), - .init( - tool: .swift, - kind: .unsafeFlags(["-secret", "value"]), - condition: .init(platformNames: ["macos", "linux"], config: "release") - ), - ]), - .init(name: "FooTests", type: .test, settings: [ - .init( - tool: .c, - kind: .define("ENABLE_BEST_MODE") - ), - .init( - tool: .cxx, - kind: .headerSearchPath("some/path"), - condition: .init(platformNames: ["macos"]) - ), - .init( - tool: .linker, - kind: .linkedLibrary("z"), - condition: .init(config: "debug") - ), - .init( - tool: .swift, - kind: .unsafeFlags(["-secret", "value"]), - condition: .init(platformNames: ["macos", "linux"], config: "release") - ), - ]), + .init( + name: "FooLib", + settings: [ + .init( + tool: .c, + kind: .define("ENABLE_BEST_MODE") + ), + .init( + tool: .cxx, + kind: .headerSearchPath("some/path"), + condition: .init(platformNames: ["macos"]) + ), + .init( + tool: .linker, + kind: .linkedLibrary("z"), + condition: .init(config: "debug") + ), + .init( + tool: .swift, + kind: .unsafeFlags(["-secret", "value"]), + condition: .init(platformNames: ["macos", "linux"], config: "release") + ), + ] + ), + .init( + name: "FooTests", + type: .test, + settings: [ + .init( + tool: .c, + kind: .define("ENABLE_BEST_MODE") + ), + .init( + tool: .cxx, + kind: .headerSearchPath("some/path"), + condition: .init(platformNames: ["macos"]) + ), + .init( + tool: .linker, + kind: .linkedLibrary("z"), + condition: .init(config: "debug") + ), + .init( + tool: .swift, + kind: .unsafeFlags(["-secret", "value"]), + condition: .init(platformNames: ["macos", "linux"], config: "release") + ), + ] + ), ] - ), + ) ], shouldCreateMultipleTestProducts: true, observabilityScope: observability.topScope @@ -2569,11 +2728,12 @@ final class PIFBuilderTests: XCTestCase { XCTAssertNoDiagnostics(observability.diagnostics) - let packageNameOptions = if isPackageAccessModifierSupported { - ["-package-name", "foo"] - } else { - [String]?.none - } + let packageNameOptions = + if isPackageAccessModifierSupported { + ["-package-name", "foo"] + } else { + [String]?.none + } try PIFTester(pif) { workspace in try workspace.checkProject("PACKAGE:/Foo") { project in @@ -2585,10 +2745,13 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "ENABLE_BEST_MODE"] ) XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], nil) - XCTAssertEqual(settings[.HEADER_SEARCH_PATHS, for: .macOS], [ - "$(inherited)", - "/Foo/Sources/foo/some/path", - ]) + XCTAssertEqual( + settings[.HEADER_SEARCH_PATHS, for: .macOS], + [ + "$(inherited)", + "/Foo/Sources/foo/some/path", + ] + ) XCTAssertEqual(settings[.OTHER_LDFLAGS], ["$(inherited)", "-lz"]) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) } @@ -2601,10 +2764,13 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "ENABLE_BEST_MODE"] ) XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], nil) - XCTAssertEqual(settings[.HEADER_SEARCH_PATHS, for: .macOS], [ - "$(inherited)", - "/Foo/Sources/foo/some/path", - ]) + XCTAssertEqual( + settings[.HEADER_SEARCH_PATHS, for: .macOS], + [ + "$(inherited)", + "/Foo/Sources/foo/some/path", + ] + ) XCTAssertEqual(settings[.OTHER_LDFLAGS], nil) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) XCTAssertEqual( @@ -2649,10 +2815,13 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "ENABLE_BEST_MODE"] ) XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], nil) - XCTAssertEqual(settings[.HEADER_SEARCH_PATHS, for: .macOS], [ - "$(inherited)", - "/Foo/Sources/FooLib/some/path", - ]) + XCTAssertEqual( + settings[.HEADER_SEARCH_PATHS, for: .macOS], + [ + "$(inherited)", + "/Foo/Sources/FooLib/some/path", + ] + ) XCTAssertEqual(settings[.OTHER_LDFLAGS], ["$(inherited)", "-lz"]) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) } @@ -2665,10 +2834,13 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "ENABLE_BEST_MODE"] ) XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], nil) - XCTAssertEqual(settings[.HEADER_SEARCH_PATHS, for: .macOS], [ - "$(inherited)", - "/Foo/Sources/FooLib/some/path", - ]) + XCTAssertEqual( + settings[.HEADER_SEARCH_PATHS, for: .macOS], + [ + "$(inherited)", + "/Foo/Sources/FooLib/some/path", + ] + ) XCTAssertEqual(settings[.OTHER_LDFLAGS], nil) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) XCTAssertEqual( @@ -2701,10 +2873,13 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "ENABLE_BEST_MODE"] ) XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], nil) - XCTAssertEqual(settings[.HEADER_SEARCH_PATHS, for: .macOS], [ - "$(inherited)", - "/Foo/Sources/FooTests/some/path", - ]) + XCTAssertEqual( + settings[.HEADER_SEARCH_PATHS, for: .macOS], + [ + "$(inherited)", + "/Foo/Sources/FooTests/some/path", + ] + ) XCTAssertEqual(settings[.OTHER_LDFLAGS], ["$(inherited)", "-lz"]) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) } @@ -2717,10 +2892,13 @@ final class PIFBuilderTests: XCTestCase { ["$(inherited)", "ENABLE_BEST_MODE"] ) XCTAssertEqual(settings[.HEADER_SEARCH_PATHS], nil) - XCTAssertEqual(settings[.HEADER_SEARCH_PATHS, for: .macOS], [ - "$(inherited)", - "/Foo/Sources/FooTests/some/path", - ]) + XCTAssertEqual( + settings[.HEADER_SEARCH_PATHS, for: .macOS], + [ + "$(inherited)", + "/Foo/Sources/FooTests/some/path", + ] + ) XCTAssertEqual(settings[.OTHER_LDFLAGS], nil) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) XCTAssertEqual( @@ -2748,11 +2926,11 @@ final class PIFBuilderTests: XCTestCase { func testConditionalDependencies() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/main.swift", + "/Foo/Sources/foo/main.swift", "/Foo/Sources/FooLib1/lib.swift", "/Foo/Sources/FooLib2/lib.swift", "/Foo/Sources/FooTests/FooTests.swift" @@ -2769,15 +2947,18 @@ final class PIFBuilderTests: XCTestCase { packageIdentity: .plain("Foo"), toolsVersion: .v5_3, targets: [ - .init(name: "foo", dependencies: [ - .target(name: "FooLib1", condition: .init(platformNames: ["macos"])), - .target(name: "FooLib2", condition: .init(platformNames: ["ios"])), - ]), + .init( + name: "foo", + dependencies: [ + .target(name: "FooLib1", condition: .init(platformNames: ["macos"])), + .target(name: "FooLib2", condition: .init(platformNames: ["ios"])), + ] + ), .init(name: "FooLib1"), .init(name: "FooLib2"), ], traits: [] - ), + ) ], shouldCreateMultipleTestProducts: true, observabilityScope: observability.topScope @@ -2804,20 +2985,27 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.dependencies, ["PACKAGE-TARGET:FooLib1", "PACKAGE-TARGET:FooLib2"]) XCTAssertEqual(target.frameworks, ["PACKAGE-TARGET:FooLib1", "PACKAGE-TARGET:FooLib2"]) - let dependencyMap = Dictionary(uniqueKeysWithValues: target.baseTarget.dependencies.map { ( - $0.targetGUID, - $0.platformFilters - ) }) + let dependencyMap = Dictionary( + uniqueKeysWithValues: target.baseTarget.dependencies.map { + ( + $0.targetGUID, + $0.platformFilters + ) + } + ) XCTAssertEqual(dependencyMap, expectedFilters) - let frameworksBuildFiles = target.baseTarget.buildPhases.first { $0 is PIF.FrameworksBuildPhase }? + let frameworksBuildFiles = + target.baseTarget.buildPhases.first { $0 is PIF.FrameworksBuildPhase }? .buildFiles ?? [] let frameworksBuildFilesMap = Dictionary( - uniqueKeysWithValues: frameworksBuildFiles - .compactMap { file -> ( - PIF.GUID, - [PIF.PlatformFilter] - )? in + uniqueKeysWithValues: + frameworksBuildFiles + .compactMap { + file -> ( + PIF.GUID, + [PIF.PlatformFilter] + )? in switch file.reference { case .target(let guid): return (guid, file.platformFilters) @@ -2834,11 +3022,11 @@ final class PIFBuilderTests: XCTestCase { func testSDKOptions() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/main.swift" + "/Foo/Sources/foo/main.swift" ) let observability = ObservabilitySystem.makeForTesting() @@ -2849,13 +3037,13 @@ final class PIFBuilderTests: XCTestCase { displayName: "Foo", path: "/Foo", platforms: [ - PlatformDescription(name: "macos", version: "10.14", options: ["best"]), + PlatformDescription(name: "macos", version: "10.14", options: ["best"]) ], toolsVersion: .v5_3, targets: [ - .init(name: "foo", dependencies: []), + .init(name: "foo", dependencies: []) ] - ), + ) ], shouldCreateMultipleTestProducts: true, observabilityScope: observability.topScope @@ -2886,11 +3074,11 @@ final class PIFBuilderTests: XCTestCase { /// works as expected. func testUnsafeFlagsBuildSettingInference() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/MyLib/Sources/MyLib/Foo.swift" + "/MyLib/Sources/MyLib/Foo.swift" ) let observability = ObservabilitySystem.makeForTesting() @@ -2902,18 +3090,21 @@ final class PIFBuilderTests: XCTestCase { path: "/MyLib", toolsVersion: .v5, products: [ - .init(name: "MyLib", type: .library(.automatic), targets: ["MyLib"]), + .init(name: "MyLib", type: .library(.automatic), targets: ["MyLib"]) ], targets: [ - .init(name: "MyLib", settings: [ - .init( - tool: .swift, - kind: .unsafeFlags(["-enable-library-evolution"]), - condition: .init(config: "release") - ), - ]), + .init( + name: "MyLib", + settings: [ + .init( + tool: .swift, + kind: .unsafeFlags(["-enable-library-evolution"]), + condition: .init(config: "release") + ) + ] + ) ] - ), + ) ], shouldCreateMultipleTestProducts: true, observabilityScope: observability.topScope @@ -2954,11 +3145,11 @@ final class PIFBuilderTests: XCTestCase { func testSupportedSwiftVersions() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/main.swift", + "/Foo/Sources/foo/main.swift", "/Foo/Sources/bar/main.swift" ) @@ -2973,15 +3164,19 @@ final class PIFBuilderTests: XCTestCase { swiftLanguageVersions: [.v4_2, .v5], targets: [ .init(name: "foo", dependencies: []), - .init(name: "bar", dependencies: [], settings: [ - .init( - tool: .swift, - kind: .swiftLanguageMode(.v4_2), - condition: .init(platformNames: ["linux"]) - ), - ]), + .init( + name: "bar", + dependencies: [], + settings: [ + .init( + tool: .swift, + kind: .swiftLanguageMode(.v4_2), + condition: .init(platformNames: ["linux"]) + ) + ] + ), ] - ), + ) ], shouldCreateMultipleTestProducts: true, observabilityScope: observability.topScope @@ -3021,17 +3216,17 @@ final class PIFBuilderTests: XCTestCase { func testPerTargetSwiftVersions() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/main.swift", + "/Foo/Sources/foo/main.swift", "/Foo/Sources/bar/main.swift", "/Foo/Sources/baz/main.swift", "/Foo/Sources/qux/main.swift" ) - let observability = ObservabilitySystem.makeForTesting(verbose: false) // Don't print expected [error]s. + let observability = ObservabilitySystem.makeForTesting(verbose: false) // Don't print expected [error]s. let graph = try loadModulesGraph( fileSystem: fs, manifests: [ @@ -3041,38 +3236,54 @@ final class PIFBuilderTests: XCTestCase { toolsVersion: .v5_3, swiftLanguageVersions: [.v4_2], targets: [ - .init(name: "foo", dependencies: [], settings: [ - .init( - tool: .swift, - kind: .swiftLanguageMode(.v4_2) - ), - ]), - .init(name: "bar", dependencies: [], settings: [ - .init( - tool: .swift, - kind: .swiftLanguageMode(.v6) - ), - ]), - .init(name: "baz", dependencies: [], settings: [ - .init( - tool: .swift, - kind: .swiftLanguageMode(.v3), - condition: .init(platformNames: ["linux"]) - ), - .init( - tool: .swift, - kind: .swiftLanguageMode(.v4_2), - condition: .init(platformNames: ["macOS"]) - ), - ]), - .init(name: "qux", dependencies: [], settings: [ - .init( - tool: .swift, - kind: .swiftLanguageMode(.v5) - ) - ]), + .init( + name: "foo", + dependencies: [], + settings: [ + .init( + tool: .swift, + kind: .swiftLanguageMode(.v4_2) + ) + ] + ), + .init( + name: "bar", + dependencies: [], + settings: [ + .init( + tool: .swift, + kind: .swiftLanguageMode(.v6) + ) + ] + ), + .init( + name: "baz", + dependencies: [], + settings: [ + .init( + tool: .swift, + kind: .swiftLanguageMode(.v3), + condition: .init(platformNames: ["linux"]) + ), + .init( + tool: .swift, + kind: .swiftLanguageMode(.v4_2), + condition: .init(platformNames: ["macOS"]) + ), + ] + ), + .init( + name: "qux", + dependencies: [], + settings: [ + .init( + tool: .swift, + kind: .swiftLanguageMode(.v5) + ) + ] + ), ] - ), + ) ], shouldCreateMultipleTestProducts: true, observabilityScope: observability.topScope @@ -3101,11 +3312,11 @@ final class PIFBuilderTests: XCTestCase { func testPerTargetDefaultIsolation() throws { #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") + try XCTSkipIf(true, "test is only supported on macOS") #endif let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/foo/foo.swift", + "/Foo/Sources/foo/foo.swift", "/Foo/Sources/bar/bar.swift", "/Foo/Sources/baz/baz.swift" ) @@ -3119,27 +3330,39 @@ final class PIFBuilderTests: XCTestCase { path: "/Foo", toolsVersion: .v6_2, targets: [ - .init(name: "foo", dependencies: [], settings: [ - .init( - tool: .swift, - kind: .defaultIsolation(.MainActor) - ), - ]), - .init(name: "bar", dependencies: [], settings: [ - .init( - tool: .swift, - kind: .defaultIsolation(.nonisolated) - ), - ]), - .init(name: "baz", dependencies: [], settings: [ - .init( - tool: .swift, - kind: .defaultIsolation(.MainActor), - condition: .init(platformNames: ["linux"]) - ) - ]) + .init( + name: "foo", + dependencies: [], + settings: [ + .init( + tool: .swift, + kind: .defaultIsolation(.MainActor) + ) + ] + ), + .init( + name: "bar", + dependencies: [], + settings: [ + .init( + tool: .swift, + kind: .defaultIsolation(.nonisolated) + ) + ] + ), + .init( + name: "baz", + dependencies: [], + settings: [ + .init( + tool: .swift, + kind: .defaultIsolation(.MainActor), + condition: .init(platformNames: ["linux"]) + ) + ] + ), ] - ), + ) ], shouldCreateMultipleTestProducts: true, observabilityScope: observability.topScope @@ -3163,7 +3386,7 @@ final class PIFBuilderTests: XCTestCase { configuration.checkBuildSettings { settings in XCTAssertMatch( settings[.OTHER_SWIFT_FLAGS] ?? [], - [.anySequence, "-default-isolation", "MainActor", .anySequence] + [.anySequence, "-default-isolation", "MainActor", .anySequence] ) } } diff --git a/Tests/XCBuildSupportTests/PIFTests.swift b/Tests/XCBuildSupportTests/PIFTests.swift index a0ec28a2187..ed92ff91809 100644 --- a/Tests/XCBuildSupportTests/PIFTests.swift +++ b/Tests/XCBuildSupportTests/PIFTests.swift @@ -20,196 +20,201 @@ import _InternalTestSupport import enum TSCBasic.JSON class PIFTests: XCTestCase { - let topLevelObject = PIF.TopLevelObject(workspace: - PIF.Workspace( - guid: "workspace", - name: "MyWorkspace", - path: "/path/to/workspace", - projects: [ - PIF.Project( - guid: "project", - name: "MyProject", - path: "/path/to/workspace/project", - projectDirectory: "/path/to/workspace/project", - developmentRegion: "fr", - buildConfigurations: [ - PIF.BuildConfiguration( - guid: "project-config-debug-guid", - name: "Debug", - buildSettings: { - var settings = PIF.BuildSettings() - settings[.PRODUCT_NAME] = "$(TARGET_NAME)" - settings[.SUPPORTED_PLATFORMS] = ["$(AVAILABLE_PLATFORMS)"] - return settings - }() - ), - PIF.BuildConfiguration( - guid: "project-config-release-guid", - name: "Release", - buildSettings: { - var settings = PIF.BuildSettings() - settings[.PRODUCT_NAME] = "$(TARGET_NAME)" - settings[.SUPPORTED_PLATFORMS] = ["$(AVAILABLE_PLATFORMS)"] - settings[.GCC_OPTIMIZATION_LEVEL] = "s" - return settings - }() - ), - ], - targets: [ - PIF.Target( - guid: "target-exe-guid", - name: "MyExecutable", - productType: .executable, - productName: "MyExecutable", - buildConfigurations: [ - PIF.BuildConfiguration( - guid: "target-exe-config-debug-guid", - name: "Debug", - buildSettings: { - var settings = PIF.BuildSettings() - settings[.TARGET_NAME] = "MyExecutable" - return settings - }() - ), - PIF.BuildConfiguration( - guid: "target-exe-config-release-guid", - name: "Release", - buildSettings: { - var settings = PIF.BuildSettings() - settings[.TARGET_NAME] = "MyExecutable" - settings[.SKIP_INSTALL] = "NO" - return settings - }() - ), - ], - buildPhases: [ - PIF.SourcesBuildPhase( - guid: "target-exe-sources-build-phase-guid", - buildFiles: [ - PIF.BuildFile( - guid: "target-exe-sources-build-file-guid", - fileGUID: "exe-file-guid", - platformFilters: [] - ) - ] - ), - PIF.FrameworksBuildPhase( - guid: "target-exe-frameworks-build-phase-guid", - buildFiles: [ - PIF.BuildFile( - guid: "target-exe-frameworks-build-file-guid", - targetGUID: "target-lib-guid", - platformFilters: [] - ) - ] - ), - PIF.HeadersBuildPhase( - guid: "target-exe-headers-build-phase-guid", - buildFiles: [ - PIF.BuildFile( - guid: "target-exe-headers-build-file-guid", - targetGUID: "target-lib-guid", - platformFilters: [], - headerVisibility: .public - ) - ] - ) - ], - dependencies: [ - .init(targetGUID: "target-lib-guid") - ], - impartedBuildSettings: PIF.BuildSettings() - ), - PIF.Target( - guid: "target-lib-guid", - name: "MyLibrary", - productType: .objectFile, - productName: "MyLibrary", - buildConfigurations: [ - PIF.BuildConfiguration( - guid: "target-lib-config-debug-guid", - name: "Debug", - buildSettings: { - var settings = PIF.BuildSettings() - settings[.TARGET_NAME] = "MyLibrary-Debug" - return settings - }(), - impartedBuildProperties: { - var settings = PIF.BuildSettings() - settings[.OTHER_CFLAGS] = ["-fmodule-map-file=modulemap", "$(inherited)"] - return PIF.ImpartedBuildProperties(settings: settings) - }() - ), - PIF.BuildConfiguration( - guid: "target-lib-config-release-guid", - name: "Release", - buildSettings: { - var settings = PIF.BuildSettings() - settings[.TARGET_NAME] = "MyLibrary" - return settings - }(), - impartedBuildProperties: { - var settings = PIF.BuildSettings() - settings[.OTHER_CFLAGS] = ["-fmodule-map-file=modulemap", "$(inherited)"] - return PIF.ImpartedBuildProperties(settings: settings) - }() - ), - ], - buildPhases: [ - PIF.SourcesBuildPhase( - guid: "target-lib-sources-build-phase-guid", - buildFiles: [ - PIF.BuildFile( - guid: "target-lib-sources-build-file-guid", - fileGUID: "lib-file-guid", - platformFilters: [] - ) - ] - ) - ], - dependencies: [], - impartedBuildSettings: PIF.BuildSettings() - ), - PIF.AggregateTarget( - guid: "aggregate-target-guid", - name: "AggregateLibrary", - buildConfigurations: [ - PIF.BuildConfiguration( - guid: "aggregate-target-config-debug-guid", - name: "Debug", - buildSettings: PIF.BuildSettings(), - impartedBuildProperties: { - var settings = PIF.BuildSettings() - settings[.OTHER_CFLAGS] = ["-fmodule-map-file=modulemap", "$(inherited)"] - return PIF.ImpartedBuildProperties(settings: settings) - }() - ), - PIF.BuildConfiguration( - guid: "aggregate-target-config-release-guid", - name: "Release", - buildSettings: PIF.BuildSettings(), - impartedBuildProperties: { - var settings = PIF.BuildSettings() - settings[.OTHER_CFLAGS] = ["-fmodule-map-file=modulemap", "$(inherited)"] - return PIF.ImpartedBuildProperties(settings: settings) - }() - ), - ], - buildPhases: [], - dependencies: [ - .init(targetGUID: "target-lib-guid"), - .init(targetGUID: "target-exe-guid"), - ], - impartedBuildSettings: PIF.BuildSettings() + let topLevelObject = PIF.TopLevelObject( + workspace: + PIF.Workspace( + guid: "workspace", + name: "MyWorkspace", + path: "/path/to/workspace", + projects: [ + PIF.Project( + guid: "project", + name: "MyProject", + path: "/path/to/workspace/project", + projectDirectory: "/path/to/workspace/project", + developmentRegion: "fr", + buildConfigurations: [ + PIF.BuildConfiguration( + guid: "project-config-debug-guid", + name: "Debug", + buildSettings: { + var settings = PIF.BuildSettings() + settings[.PRODUCT_NAME] = "$(TARGET_NAME)" + settings[.SUPPORTED_PLATFORMS] = ["$(AVAILABLE_PLATFORMS)"] + return settings + }() + ), + PIF.BuildConfiguration( + guid: "project-config-release-guid", + name: "Release", + buildSettings: { + var settings = PIF.BuildSettings() + settings[.PRODUCT_NAME] = "$(TARGET_NAME)" + settings[.SUPPORTED_PLATFORMS] = ["$(AVAILABLE_PLATFORMS)"] + settings[.GCC_OPTIMIZATION_LEVEL] = "s" + return settings + }() + ), + ], + targets: [ + PIF.Target( + guid: "target-exe-guid", + name: "MyExecutable", + productType: .executable, + productName: "MyExecutable", + buildConfigurations: [ + PIF.BuildConfiguration( + guid: "target-exe-config-debug-guid", + name: "Debug", + buildSettings: { + var settings = PIF.BuildSettings() + settings[.TARGET_NAME] = "MyExecutable" + return settings + }() + ), + PIF.BuildConfiguration( + guid: "target-exe-config-release-guid", + name: "Release", + buildSettings: { + var settings = PIF.BuildSettings() + settings[.TARGET_NAME] = "MyExecutable" + settings[.SKIP_INSTALL] = "NO" + return settings + }() + ), + ], + buildPhases: [ + PIF.SourcesBuildPhase( + guid: "target-exe-sources-build-phase-guid", + buildFiles: [ + PIF.BuildFile( + guid: "target-exe-sources-build-file-guid", + fileGUID: "exe-file-guid", + platformFilters: [] + ) + ] + ), + PIF.FrameworksBuildPhase( + guid: "target-exe-frameworks-build-phase-guid", + buildFiles: [ + PIF.BuildFile( + guid: "target-exe-frameworks-build-file-guid", + targetGUID: "target-lib-guid", + platformFilters: [] + ) + ] + ), + PIF.HeadersBuildPhase( + guid: "target-exe-headers-build-phase-guid", + buildFiles: [ + PIF.BuildFile( + guid: "target-exe-headers-build-file-guid", + targetGUID: "target-lib-guid", + platformFilters: [], + headerVisibility: .public + ) + ] + ), + ], + dependencies: [ + .init(targetGUID: "target-lib-guid") + ], + impartedBuildSettings: PIF.BuildSettings() + ), + PIF.Target( + guid: "target-lib-guid", + name: "MyLibrary", + productType: .objectFile, + productName: "MyLibrary", + buildConfigurations: [ + PIF.BuildConfiguration( + guid: "target-lib-config-debug-guid", + name: "Debug", + buildSettings: { + var settings = PIF.BuildSettings() + settings[.TARGET_NAME] = "MyLibrary-Debug" + return settings + }(), + impartedBuildProperties: { + var settings = PIF.BuildSettings() + settings[.OTHER_CFLAGS] = ["-fmodule-map-file=modulemap", "$(inherited)"] + return PIF.ImpartedBuildProperties(settings: settings) + }() + ), + PIF.BuildConfiguration( + guid: "target-lib-config-release-guid", + name: "Release", + buildSettings: { + var settings = PIF.BuildSettings() + settings[.TARGET_NAME] = "MyLibrary" + return settings + }(), + impartedBuildProperties: { + var settings = PIF.BuildSettings() + settings[.OTHER_CFLAGS] = ["-fmodule-map-file=modulemap", "$(inherited)"] + return PIF.ImpartedBuildProperties(settings: settings) + }() + ), + ], + buildPhases: [ + PIF.SourcesBuildPhase( + guid: "target-lib-sources-build-phase-guid", + buildFiles: [ + PIF.BuildFile( + guid: "target-lib-sources-build-file-guid", + fileGUID: "lib-file-guid", + platformFilters: [] + ) + ] + ) + ], + dependencies: [], + impartedBuildSettings: PIF.BuildSettings() + ), + PIF.AggregateTarget( + guid: "aggregate-target-guid", + name: "AggregateLibrary", + buildConfigurations: [ + PIF.BuildConfiguration( + guid: "aggregate-target-config-debug-guid", + name: "Debug", + buildSettings: PIF.BuildSettings(), + impartedBuildProperties: { + var settings = PIF.BuildSettings() + settings[.OTHER_CFLAGS] = ["-fmodule-map-file=modulemap", "$(inherited)"] + return PIF.ImpartedBuildProperties(settings: settings) + }() + ), + PIF.BuildConfiguration( + guid: "aggregate-target-config-release-guid", + name: "Release", + buildSettings: PIF.BuildSettings(), + impartedBuildProperties: { + var settings = PIF.BuildSettings() + settings[.OTHER_CFLAGS] = ["-fmodule-map-file=modulemap", "$(inherited)"] + return PIF.ImpartedBuildProperties(settings: settings) + }() + ), + ], + buildPhases: [], + dependencies: [ + .init(targetGUID: "target-lib-guid"), + .init(targetGUID: "target-exe-guid"), + ], + impartedBuildSettings: PIF.BuildSettings() + ), + ], + groupTree: PIF.Group( + guid: "main-group-guid", + path: "", + children: [ + PIF.FileReference(guid: "exe-file-guid", path: "main.swift"), + PIF.FileReference(guid: "lib-file-guid", path: "lib.swift"), + ] ) - ], - groupTree: PIF.Group(guid: "main-group-guid", path: "", children: [ - PIF.FileReference(guid: "exe-file-guid", path: "main.swift"), - PIF.FileReference(guid: "lib-file-guid", path: "lib.swift"), - ]) - ) - ] - ) + ) + ] + ) ) func testRoundTrip() throws { @@ -292,11 +297,14 @@ class PIFTests: XCTestCase { XCTAssertEqual(projectContents["projectIsPackage"]?.string, "true") XCTAssertEqual(projectContents["developmentRegion"]?.string, "fr") XCTAssertEqual(projectContents["defaultConfigurationName"]?.string, "Release") - XCTAssertEqual(projectContents["targets"]?.array, [ - exeTarget["signature"]!, - libTarget["signature"]!, - aggregateTarget["signature"]!, - ]) + XCTAssertEqual( + projectContents["targets"]?.array, + [ + exeTarget["signature"]!, + libTarget["signature"]!, + aggregateTarget["signature"]!, + ] + ) if let configurations = projectContents["buildConfigurations"]?.array, configurations.count == 2 { let debugConfiguration = configurations[0] @@ -349,11 +357,14 @@ class PIFTests: XCTestCase { XCTAssertEqual(exeTargetContents["productTypeIdentifier"]?.string, "com.apple.product-type.tool") XCTAssertEqual(exeTargetContents["buildRules"]?.array, []) - XCTAssertEqual(exeTargetContents["productReference"], JSON([ - "type": "file", - "guid": "PRODUCTREF-target-exe-guid", - "name": "MyExecutable" - ])) + XCTAssertEqual( + exeTargetContents["productReference"], + JSON([ + "type": "file", + "guid": "PRODUCTREF-target-exe-guid", + "name": "MyExecutable", + ]) + ) if let configurations = exeTargetContents["buildConfigurations"]?.array, configurations.count == 2 { let debugConfiguration = configurations[0] @@ -417,11 +428,14 @@ class PIFTests: XCTestCase { XCTAssertEqual(libTargetContents["productTypeIdentifier"]?.string, "com.apple.product-type.objfile") XCTAssertEqual(libTargetContents["buildRules"]?.array, []) - XCTAssertEqual(libTargetContents["productReference"], JSON([ - "type": "file", - "guid": "PRODUCTREF-target-lib-guid", - "name": "MyLibrary" - ])) + XCTAssertEqual( + libTargetContents["productReference"], + JSON([ + "type": "file", + "guid": "PRODUCTREF-target-lib-guid", + "name": "MyLibrary", + ]) + ) if let configurations = libTargetContents["buildConfigurations"]?.array, configurations.count == 2 { let debugConfiguration = configurations[0] @@ -465,10 +479,13 @@ class PIFTests: XCTestCase { XCTAssertEqual(aggregateTargetContents["guid"]?.string, "aggregate-target-guid@11") XCTAssertEqual(aggregateTargetContents["type"]?.string, "aggregate") XCTAssertEqual(aggregateTargetContents["name"]?.string, "AggregateLibrary") - XCTAssertEqual(aggregateTargetContents["dependencies"]?.array, [ - JSON(["guid": "target-lib-guid@11"]), - JSON(["guid": "target-exe-guid@11"]), - ]) + XCTAssertEqual( + aggregateTargetContents["dependencies"]?.array, + [ + JSON(["guid": "target-lib-guid@11"]), + JSON(["guid": "target-exe-guid@11"]), + ] + ) XCTAssertEqual(aggregateTargetContents["buildRules"], nil) if let configurations = aggregateTargetContents["buildConfigurations"]?.array, configurations.count == 2 { diff --git a/Tests/_InternalTestSupportTests/MiscTests.swift b/Tests/_InternalTestSupportTests/MiscTests.swift index 26b8a838fd4..319e98b7f9a 100644 --- a/Tests/_InternalTestSupportTests/MiscTests.swift +++ b/Tests/_InternalTestSupportTests/MiscTests.swift @@ -37,19 +37,19 @@ struct TestGetNumberOfMatches { ( matchOn: "", value: """ - This is a non-empty string - This is the second line - This is the third line - """, + This is a non-empty string + This is the second line + This is the third line + """, expectedNumMatches: 0, id: "Empty string matches on non-empty multiline string using triple double quotes zero times", ), ( matchOn: """ - This is a non-empty string - This is the second line - This is the third line - """, + This is a non-empty string + This is the second line + This is the third line + """, value: "", expectedNumMatches: 0, id: "non-empty string matches on empty string zero times", @@ -57,45 +57,45 @@ struct TestGetNumberOfMatches { ( matchOn: "error: fatalError", value: """ - > swift test 25/10/24 10:44:14 - Building for debugging... - /Users/arandomuser/Documents/personal/repro-swiftpm-6605/Tests/repro-swiftpm-6605Tests/repro_swiftpm_6605Tests.swift:7:19: error: division by zero - let y = 1 / x - ^ - error: fatalError + > swift test 25/10/24 10:44:14 + Building for debugging... + /Users/arandomuser/Documents/personal/repro-swiftpm-6605/Tests/repro-swiftpm-6605Tests/repro_swiftpm_6605Tests.swift:7:19: error: division by zero + let y = 1 / x + ^ + error: fatalError - error: fatalError - """, + error: fatalError + """, expectedNumMatches: 2, id: "fatal error matches on multiline with two occurrences returns two", ), ( matchOn: "\nerror: fatalError", value: """ - > swift test 25/10/24 10:44:14 - Building for debugging... - /Users/arandomuser/Documents/personal/repro-swiftpm-6605/Tests/repro-swiftpm-6605Tests/repro_swiftpm_6605Tests.swift:7:19: error: division by zero - let y = 1 / x - ^ - error: fatalError + > swift test 25/10/24 10:44:14 + Building for debugging... + /Users/arandomuser/Documents/personal/repro-swiftpm-6605/Tests/repro-swiftpm-6605Tests/repro_swiftpm_6605Tests.swift:7:19: error: division by zero + let y = 1 / x + ^ + error: fatalError - error: fatalError - """, + error: fatalError + """, expectedNumMatches: 2, id: "fatal error with leading new line matches on multi line with two occurences returns two", ), ( matchOn: "\nerror: fatalError\n", value: """ - > swift test 25/10/24 10:44:14 - Building for debugging... - /Users/arandomuser/Documents/personal/repro-swiftpm-6605/Tests/repro-swiftpm-6605Tests/repro_swiftpm_6605Tests.swift:7:19: error: division by zero - let y = 1 / x - ^ - error: fatalError + > swift test 25/10/24 10:44:14 + Building for debugging... + /Users/arandomuser/Documents/personal/repro-swiftpm-6605/Tests/repro-swiftpm-6605Tests/repro_swiftpm_6605Tests.swift:7:19: error: division by zero + let y = 1 / x + ^ + error: fatalError - error: fatalError - """, + error: fatalError + """, expectedNumMatches: 1, id: "fatal error with leading and trailing new line matches on multi line with two occurences returns two", ), @@ -117,7 +117,7 @@ struct TestGetBuildSystemArgs { @Test func nilArgumentReturnsEmptyArray() { let expected: [String] = [] - let inputUnderTest: BuildSystemProvider.Kind? = nil + let inputUnderTest: BuildSystemProvider.Kind? = nil let actual = getBuildSystemArgs(for: inputUnderTest) @@ -130,7 +130,7 @@ struct TestGetBuildSystemArgs { func validArgumentsReturnsCorrectCommandLineArguments(_ inputValue: BuildSystemProvider.Kind) { let expected = [ "--build-system", - "\(inputValue)" + "\(inputValue)", ] let actual = getBuildSystemArgs(for: inputValue) diff --git a/Tests/_InternalTestSupportTests/XCTAssertHelpersTests.swift b/Tests/_InternalTestSupportTests/XCTAssertHelpersTests.swift index d8b73adb2d0..d1e01f7b34f 100644 --- a/Tests/_InternalTestSupportTests/XCTAssertHelpersTests.swift +++ b/Tests/_InternalTestSupportTests/XCTAssertHelpersTests.swift @@ -27,12 +27,12 @@ final class TestRequiresTool: XCTestCase { func testErrorIsNotThrownIfExecutableIsOnThePath() throws { // Essentially call either "which which" or "where.exe where.exe" #if os(Windows) - let executable = "where.exe" + let executable = "where.exe" #else - let executable = "which" + let executable = "which" #endif XCTAssertNoThrow( try _requiresTools(executable) ) } -} \ No newline at end of file +} diff --git a/Utilities/Certificates/Package.swift b/Utilities/Certificates/Package.swift index dc936bdbcfe..e8a22507469 100644 --- a/Utilities/Certificates/Package.swift +++ b/Utilities/Certificates/Package.swift @@ -5,12 +5,14 @@ import PackageDescription let package = Package( name: "Certificates", targets: [ - .target(name: "Certificates", - path: ".", - exclude: ["README.md", "generate.sh"], - resources: [ - .embedInCode("Intermediates"), - .embedInCode("Roots"), - ]), + .target( + name: "Certificates", + path: ".", + exclude: ["README.md", "generate.sh"], + resources: [ + .embedInCode("Intermediates"), + .embedInCode("Roots"), + ] + ) ] ) diff --git a/Utilities/InstalledSwiftPMConfiguration/Package.swift b/Utilities/InstalledSwiftPMConfiguration/Package.swift index 4b230cc0737..5fac7b42bab 100644 --- a/Utilities/InstalledSwiftPMConfiguration/Package.swift +++ b/Utilities/InstalledSwiftPMConfiguration/Package.swift @@ -7,6 +7,6 @@ let package = Package( targets: [ .executableTarget( name: "InstalledSwiftPMConfiguration" - ), + ) ] ) diff --git a/Utilities/InstalledSwiftPMConfiguration/Sources/exec.swift b/Utilities/InstalledSwiftPMConfiguration/Sources/exec.swift index 44a912f5085..cbeb04f1887 100644 --- a/Utilities/InstalledSwiftPMConfiguration/Sources/exec.swift +++ b/Utilities/InstalledSwiftPMConfiguration/Sources/exec.swift @@ -2,9 +2,9 @@ import Foundation @main struct Exec { - static func main() throws { - let config = InstalledSwiftPMConfiguration(version: 1, swiftSyntaxVersionForMacroTemplate: .init(major: 509, minor: 0, patch: 0)) - let data = try JSONEncoder().encode(config) - try data.write(to: URL(fileURLWithPath: "config.json")) - } + static func main() throws { + let config = InstalledSwiftPMConfiguration(version: 1, swiftSyntaxVersionForMacroTemplate: .init(major: 509, minor: 0, patch: 0)) + let data = try JSONEncoder().encode(config) + try data.write(to: URL(fileURLWithPath: "config.json")) + } }