From a0c88d905923029311994aafd500b19ce747f7d0 Mon Sep 17 00:00:00 2001 From: Bartosz Polaczyk Date: Sun, 21 Nov 2021 19:40:06 +0100 Subject: [PATCH 1/5] Provide a reason why SPM dependencies cannot be supported --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 54cf08a..65b7e33 100755 --- a/README.md +++ b/README.md @@ -372,7 +372,7 @@ Head over to our [cocoapods-plugin](cocoapods-plugin/README.md) docs to see how ## Limitations -* Swift Package Manager (SPM) projects are not supported +* Swift Package Manager (SPM) dependencies are not supported. _Because SPM does not allow customizing Build Settings, XCRemoteCache cannot specify `clang` and `swiftc` wrappers that control if the local compilation should be skipped (cache hit) or not (cache miss)_ * Filenames with `_vers.c` suffix are reserved and cannot be used as a source file * All compilation files should be referenced via the git repo root. Referencing `/AbsolutePath/someOther.swift` or `../../someOther.swift` that resolve to the location outside of the git repo root is prohibited. From ba41e40bb00cb953e21a4a033252627e94f5fdf4 Mon Sep 17 00:00:00 2001 From: Mihai Seremet Date: Sat, 20 Nov 2021 18:15:46 +0200 Subject: [PATCH 2/5] Reuse existing build phases in CocoaPods plugin --- .gitignore | 3 +- .../cocoapods-xcremotecache/command/hooks.rb | 95 +++++++++++-------- 2 files changed, 55 insertions(+), 43 deletions(-) diff --git a/.gitignore b/.gitignore index 8f32b09..27a6e4d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ DerivedData /.swiftpm/ releases -tmp/ \ No newline at end of file +tmp/ +.idea/ diff --git a/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb b/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb index 0873f0a..36bf660 100644 --- a/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb +++ b/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb @@ -46,17 +46,17 @@ module CocoapodsXCRemoteCacheModifier @@configuration = c end - def self.set_configuration_default_values(user_proj_directory) + def self.set_configuration_default_values default_values = { 'mode' => 'consumer', 'enabled' => true, - 'xcrc_location' => "#{user_proj_directory}/XCRC", + 'xcrc_location' => "XCRC", 'exclude_build_configurations' => [], 'check_build_configuration' => 'Debug', 'check_platform' => 'iphonesimulator', 'modify_lldb_init' => true, - 'xccc_file' => "#{user_proj_directory}/#{BIN_DIR}/xccc", - 'remote_commit_file' => "#{user_proj_directory}/#{BIN_DIR}/arc.rc", + 'xccc_file' => "#{BIN_DIR}/xccc", + 'remote_commit_file' => "#{BIN_DIR}/arc.rc", 'exclude_targets' => [], } @@configuration.merge! default_values.select { |k, v| !@@configuration.key?(k) } @@ -89,61 +89,67 @@ module CocoapodsXCRemoteCacheModifier @@configuration.select { |key, value| !CUSTOM_CONFIGURATION_KEYS.include?(key) } end - def self.enable_xcremotecache(target, user_proj_directory, xc_location, xc_cc_path, mode, exclude_build_configurations, check_build_configuration, check_platform, final_target) - target.build_configurations.each do |config| - # apply only for relevant Configurations - next if exclude_build_configurations.include?(config.name) - if mode == 'consumer' - config.build_settings['CC'] = [xc_cc_path] - end - config.build_settings['SWIFT_EXEC'] = ["#{xc_location}/xcswiftc"] - config.build_settings['LIBTOOL'] = ["#{xc_location}/xclibtool"] - config.build_settings['LD'] = ["#{xc_location}/xcld"] - - config.build_settings['XCREMOTE_CACHE_FAKE_SRCROOT'] = FAKE_SRCROOT - add_cflags!(config.build_settings, '-fdebug-prefix-map', "#{user_proj_directory}=$(XCREMOTE_CACHE_FAKE_SRCROOT)") - add_swiftflags!(config.build_settings, '-debug-prefix-map', "#{user_proj_directory}=$(XCREMOTE_CACHE_FAKE_SRCROOT)") + def self.enable_xcremotecache(target, xc_location, xc_cc_path, mode, exclude_build_configurations, final_target) + target.build_configurations.each do |config| + # apply only for relevant Configurations + next if exclude_build_configurations.include?(config.name) + if mode == 'consumer' + config.build_settings['CC'] = ["$SRCROOT/#{xc_cc_path}"] end - + config.build_settings['SWIFT_EXEC'] = ["$SRCROOT/#{xc_location}/xcswiftc"] + config.build_settings['LIBTOOL'] = ["$SRCROOT/#{xc_location}/xclibtool"] + config.build_settings['LD'] = ["$SRCROOT/#{xc_location}/xcld"] - # User project is not generated from scratch (contrary to `Pods`), delete all previous XCRemoteCache phases - target.build_phases.delete_if {|phase| - # Some phases (e.g. PBXSourcesBuildPhase) don't have strict name check respond_to? - if phase.respond_to?(:name) - phase.name != nil && phase.name.start_with?("[XCRC]") - end - } + config.build_settings['XCREMOTE_CACHE_FAKE_SRCROOT'] = FAKE_SRCROOT + add_cflags!(config.build_settings, '-fdebug-prefix-map', "$SRCROOT=$(XCREMOTE_CACHE_FAKE_SRCROOT)") + add_swiftflags!(config.build_settings, '-debug-prefix-map', "$SRCROOT=$(XCREMOTE_CACHE_FAKE_SRCROOT)") + end # Prebuild if mode == 'consumer' - prebuild_script = target.new_shell_script_build_phase("[XCRC] Prebuild") + existing_prebuild_script = target.build_phases.detect do |phase| + if phase.respond_to?(:name) + phase.name != nil && phase.name.start_with?("[XCRC] Prebuild") + end + end + prebuild_script = existing_prebuild_script || target.new_shell_script_build_phase("[XCRC] Prebuild") prebuild_script.shell_script = "\"$SCRIPT_INPUT_FILE_0\"" - prebuild_script.input_paths = ["#{xc_location}/xcprebuild"] + prebuild_script.input_paths = ["$SRCROOT/#{xc_location}/xcprebuild"] prebuild_script.output_paths = [ - "$(TARGET_TEMP_DIR)/rc.enabled", + "$(TARGET_TEMP_DIR)/rc.enabled", "$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)" ] prebuild_script.dependency_file = "$(TARGET_TEMP_DIR)/prebuild.d" # Move prebuild (last element) to the first position (to make it real 'prebuild') - target.build_phases.rotate!(-1) + target.build_phases.rotate!(-1) if existing_prebuild_script.nil? end # Postbuild - postbuild_script = target.new_shell_script_build_phase("[XCRC] Postbuild") + existing_postbuild_script = target.build_phases.detect do |phase| + if phase.respond_to?(:name) + phase.name != nil && phase.name.start_with?("[XCRC] Postbuild") + end + end + postbuild_script = existing_postbuild_script || target.new_shell_script_build_phase("[XCRC] Postbuild") postbuild_script.shell_script = "\"$SCRIPT_INPUT_FILE_0\"" - postbuild_script.input_paths = ["#{xc_location}/xcpostbuild"] + postbuild_script.input_paths = ["$SRCROOT/#{xc_location}/xcpostbuild"] postbuild_script.output_paths = [ - "$(TARGET_BUILD_DIR)/$(MODULES_FOLDER_PATH)/$(PRODUCT_MODULE_NAME).swiftmodule/$(PLATFORM_PREFERRED_ARCH).swiftmodule.md5", + "$(TARGET_BUILD_DIR)/$(MODULES_FOLDER_PATH)/$(PRODUCT_MODULE_NAME).swiftmodule/$(PLATFORM_PREFERRED_ARCH).swiftmodule.md5", "$(TARGET_BUILD_DIR)/$(MODULES_FOLDER_PATH)/$(PRODUCT_MODULE_NAME).swiftmodule/$(PLATFORM_PREFERRED_ARCH)-$(LLVM_TARGET_TRIPLE_VENDOR)-$(SWIFT_PLATFORM_TARGET_PREFIX)$(LLVM_TARGET_TRIPLE_SUFFIX).swiftmodule.md5" ] postbuild_script.dependency_file = "$(TARGET_TEMP_DIR)/postbuild.d" # Mark a sha as ready for a given platform and configuration when building the final_target if mode == 'producer' && target.name == final_target - mark_script = target.new_shell_script_build_phase("[XCRC] Mark") + existing_mark_script = target.build_phases.detect do |phase| + if phase.respond_to?(:name) + phase.name != nil && phase.name.start_with?("[XCRC] Mark") + end + end + mark_script = existing_mark_script || target.new_shell_script_build_phase("[XCRC] Mark") mark_script.shell_script = "\"$SCRIPT_INPUT_FILE_0\" mark --configuration $CONFIGURATION --platform $PLATFORM_NAME" - mark_script.input_paths = ["#{xc_location}/xcprepare"] + mark_script.input_paths = ["$SRCROOT/#{xc_location}/xcprepare"] end end @@ -251,6 +257,7 @@ module CocoapodsXCRemoteCacheModifier # Returns the content (array of lines) of the lldbinit with stripped XCRemoteCache rewrite def self.clean_lldbinit_content(lldbinit_path) all_lines = [] + return all_lines unless File.exist?(lldbinit_path) File.open(lldbinit_path) { |file| while(line = file.gets) != nil line = line.strip @@ -290,7 +297,7 @@ module CocoapodsXCRemoteCacheModifier begin user_proj_directory = File.dirname(user_project.path) - set_configuration_default_values(user_proj_directory) + set_configuration_default_values unless @@configuration['enabled'] Pod::UI.puts "[XCRC] XCRemoteCache disabled" @@ -310,8 +317,12 @@ module CocoapodsXCRemoteCacheModifier check_build_configuration = @@configuration['check_build_configuration'] check_platform = @@configuration['check_platform'] + xccc_location_absolute = "#{user_proj_directory}/#{xccc_location}" + xcrc_location_absolute = "#{user_proj_directory}/#{xcrc_location}" + remote_commit_file_absolute = "#{user_proj_directory}/#{remote_commit_file}" + # Download XCRC - download_xcrc_if_needed(xcrc_location) + download_xcrc_if_needed(xcrc_location_absolute) # Save .rcinfo save_rcinfo(generate_rcinfo(), user_proj_directory) @@ -320,12 +331,12 @@ module CocoapodsXCRemoteCacheModifier Dir.mkdir(BIN_DIR) unless File.exist?(BIN_DIR) # Remove previous xccc & arc.rc - File.delete(remote_commit_file) if File.exist?(remote_commit_file) - File.delete(xccc_location) if File.exist?(xccc_location) + File.delete(remote_commit_file_absolute) if File.exist?(remote_commit_file_absolute) + File.delete(xccc_location_absolute) if File.exist?(xccc_location_absolute) # Prepare XCRC begin - prepare_result = YAML.load`#{xcrc_location}/xcprepare --configuration #{check_build_configuration} --platform #{check_platform}` + prepare_result = YAML.load`#{xcrc_location_absolute}/xcprepare --configuration #{check_build_configuration} --platform #{check_platform}` unless prepare_result['result'] || mode != 'consumer' # Uninstall the XCRemoteCache for the consumer mode disable_xcremotecache(user_project) @@ -343,7 +354,7 @@ module CocoapodsXCRemoteCacheModifier next if target.name.start_with?("Pods-") next if target.name.end_with?("Tests") next if exclude_targets.include?(target.name) - enable_xcremotecache(target, user_proj_directory, xcrc_location, xccc_location, mode, exclude_build_configurations, check_build_configuration, check_platform, final_target) + enable_xcremotecache(target, "../#{xcrc_location}", "../#{xccc_location}", mode, exclude_build_configurations, final_target) end # Create .rcinfo into `Pods` directory as that .xcodeproj reads configuration from .xcodeproj location @@ -357,7 +368,7 @@ module CocoapodsXCRemoteCacheModifier # Attach XCRC to the app targets user_project.targets.each do |target| next if exclude_targets.include?(target.name) - enable_xcremotecache(target, user_proj_directory, xcrc_location, xccc_location, mode, exclude_build_configurations, check_build_configuration, check_platform, final_target) + enable_xcremotecache(target, xcrc_location, xccc_location, mode, exclude_build_configurations, final_target) end # Set Target sourcemap From 4f1f73132e9a4477e43b5790310c4a007ac36c4a Mon Sep 17 00:00:00 2001 From: Mihai Seremet Date: Tue, 23 Nov 2021 00:28:08 +0200 Subject: [PATCH 3/5] Support switching between models in plugin --- .../lib/cocoapods-xcremotecache/command/hooks.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb b/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb index 36bf660..2996ea1 100644 --- a/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb +++ b/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb @@ -123,6 +123,13 @@ module CocoapodsXCRemoteCacheModifier # Move prebuild (last element) to the first position (to make it real 'prebuild') target.build_phases.rotate!(-1) if existing_prebuild_script.nil? + elsif mode == 'producer' + # Delete existing prebuild build phase (to support switching between modes) + target.build_phases.delete_if do |phase| + if phase.respond_to?(:name) + phase.name != nil && phase.name.start_with?("[XCRC] Prebuild") + end + end end # Postbuild @@ -150,6 +157,13 @@ module CocoapodsXCRemoteCacheModifier mark_script = existing_mark_script || target.new_shell_script_build_phase("[XCRC] Mark") mark_script.shell_script = "\"$SCRIPT_INPUT_FILE_0\" mark --configuration $CONFIGURATION --platform $PLATFORM_NAME" mark_script.input_paths = ["$SRCROOT/#{xc_location}/xcprepare"] + else + # Delete existing mark build phase (to support switching between modes or changing the final target) + target.build_phases.delete_if do |phase| + if phase.respond_to?(:name) + phase.name != nil && phase.name.start_with?("[XCRC] Mark") + end + end end end From 86273017b484c25a0504bcdb27464896b43ebe89 Mon Sep 17 00:00:00 2001 From: Mihai Seremet Date: Wed, 24 Nov 2021 12:23:46 +0200 Subject: [PATCH 4/5] Fix debugging for Pods project --- cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb b/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb index 2996ea1..efbf37b 100644 --- a/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb +++ b/cocoapods-plugin/lib/cocoapods-xcremotecache/command/hooks.rb @@ -101,8 +101,8 @@ module CocoapodsXCRemoteCacheModifier config.build_settings['LD'] = ["$SRCROOT/#{xc_location}/xcld"] config.build_settings['XCREMOTE_CACHE_FAKE_SRCROOT'] = FAKE_SRCROOT - add_cflags!(config.build_settings, '-fdebug-prefix-map', "$SRCROOT=$(XCREMOTE_CACHE_FAKE_SRCROOT)") - add_swiftflags!(config.build_settings, '-debug-prefix-map', "$SRCROOT=$(XCREMOTE_CACHE_FAKE_SRCROOT)") + add_cflags!(config.build_settings, '-fdebug-prefix-map', "$(SRCROOT:dir:standardizepath)=$(XCREMOTE_CACHE_FAKE_SRCROOT)") + add_swiftflags!(config.build_settings, '-debug-prefix-map', "$(SRCROOT:dir:standardizepath)=$(XCREMOTE_CACHE_FAKE_SRCROOT)") end # Prebuild From 5c568a13381e6a5baea11bcf11645cdcdb40b216 Mon Sep 17 00:00:00 2001 From: Vladislav Klimenko Date: Wed, 24 Nov 2021 21:07:40 +0300 Subject: [PATCH 5/5] Fix SwiftLint warnings --- .swiftlint.yml | 1 + Rakefile | 2 +- .../ThinningDiskSwiftcProductsGenerator.swift | 2 +- .../Commands/Prebuild/Prebuild.swift | 1 + .../Commands/Prebuild/XCPrebuild.swift | 5 +- .../Commands/Prepare/CCWrapperBuilder.swift | 5 +- .../Prepare/Integrate/LLDBInitPatcher.swift | 4 +- .../Prepare/Integrate/XCIntegrate.swift | 3 +- .../Integrate/XcodeProjIntegrate.swift | 5 +- .../Integrate/XcodeSettingsFlags.swift | 2 +- .../Commands/Prepare/XCPrepareMark.swift | 1 + .../Commands/Swiftc/XCSwiftc.swift | 5 +- .../Config/XCRemoteCacheConfig.swift | 10 ++-- .../Authentication/AWSV4Signature.swift | 19 +++++-- .../Network/Authentication/HMAC.swift | 9 +++- .../XCRemoteCache/Stats/CacheHitLogger.swift | 17 ++++--- ...rtifactSwiftProductsBuilderImplTests.swift | 43 ++++++++++++---- .../Integrate/FileLLDBInitPatcherTests.swift | 1 + .../SwiftcFilemapInputEditorTests.swift | 49 ++++++++++--------- .../Commands/SwiftcTests.swift | 6 ++- .../FileFingerprintSyncerTests.swift | 1 + .../TargetDependenciesReaderTests.swift | 1 + .../Copier/CopyDiskCopierTests.swift | 1 + .../FilteredInvocationStorageTests.swift | 1 + .../Output/InvocationFileStorageTests.swift | 1 + .../ActionSpecificCacheHitLoggerTests.swift | 1 + 26 files changed, 136 insertions(+), 60 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 8530898..57e9c93 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -5,6 +5,7 @@ disabled_rules: - superfluous_disable_command # Disabled since we disable some rules pre-emptively to avoid issues in the future - todo # Temporarily disabled. We have too many right now hiding real issues :( - nesting # Does not make sense anymore since Swift 4 uses nested `CodingKeys` enums for example + - trailing_dot_in_comments # Triggers warnings for generated file headers opt_in_rules: - anyobject_protocol diff --git a/Rakefile b/Rakefile index f366603..2563fe2 100644 --- a/Rakefile +++ b/Rakefile @@ -28,7 +28,7 @@ task :lint => [:prepare] do puts 'Run linting' system("swiftformat --lint --config .swiftformat --cache ignore .") or abort "swiftformat failure" if SWIFTFORMAT_ENABLED - system("swiftlint lint --config .swiftlint.yml") or abort "swiftlint failure" if SWIFTLINT_ENABLED + system("swiftlint lint --config .swiftlint.yml --strict") or abort "swiftlint failure" if SWIFTLINT_ENABLED end task :autocorrect => [:prepare] do diff --git a/Sources/XCRemoteCache/Commands/Plugins/Thinning/ThinningDiskSwiftcProductsGenerator.swift b/Sources/XCRemoteCache/Commands/Plugins/Thinning/ThinningDiskSwiftcProductsGenerator.swift index ec090e2..74f023e 100644 --- a/Sources/XCRemoteCache/Commands/Plugins/Thinning/ThinningDiskSwiftcProductsGenerator.swift +++ b/Sources/XCRemoteCache/Commands/Plugins/Thinning/ThinningDiskSwiftcProductsGenerator.swift @@ -40,7 +40,7 @@ class ThinningDiskSwiftcProductsGenerator: SwiftcProductsGenerator { destinationSwiftmodulePaths = Dictionary( uniqueKeysWithValues: SwiftmoduleFileExtension.SwiftmoduleExtensions .map { ext, _ in - switch (ext) { + switch ext { case .swiftsourceinfo: let dest = modulePathDir.appendingPathComponent("Project") .appendingPathComponent(moduleName) diff --git a/Sources/XCRemoteCache/Commands/Prebuild/Prebuild.swift b/Sources/XCRemoteCache/Commands/Prebuild/Prebuild.swift index 5094ec3..23d9655 100644 --- a/Sources/XCRemoteCache/Commands/Prebuild/Prebuild.swift +++ b/Sources/XCRemoteCache/Commands/Prebuild/Prebuild.swift @@ -55,6 +55,7 @@ class Prebuild { self.artifactConsumerPrebuildPlugins = artifactConsumerPrebuildPlugins } + // swiftlint:disable:next function_body_length public func perform() throws -> PrebuildResult { guard case .available(let commit) = context.remoteCommit else { return .incompatible diff --git a/Sources/XCRemoteCache/Commands/Prebuild/XCPrebuild.swift b/Sources/XCRemoteCache/Commands/Prebuild/XCPrebuild.swift index 07e1ecd..46878cf 100644 --- a/Sources/XCRemoteCache/Commands/Prebuild/XCPrebuild.swift +++ b/Sources/XCRemoteCache/Commands/Prebuild/XCPrebuild.swift @@ -129,7 +129,10 @@ public class XCPrebuild { algorithm: MD5Algorithm() ) let organizer = ZipArtifactOrganizer(targetTempDir: context.targetTempDir, fileManager: fileManager) - let compilationHistoryOrganizer = CompilationHistoryFileOrganizer(context.compilationHistoryFile, fileManager: fileManager) + let compilationHistoryOrganizer = CompilationHistoryFileOrganizer( + context.compilationHistoryFile, + fileManager: fileManager + ) let metaReader = JsonMetaReader(fileAccessor: fileManager) var consumerPlugins: [ArtifactConsumerPrebuildPlugin] = [] diff --git a/Sources/XCRemoteCache/Commands/Prepare/CCWrapperBuilder.swift b/Sources/XCRemoteCache/Commands/Prepare/CCWrapperBuilder.swift index 8704630..bd6f9fa 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/CCWrapperBuilder.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/CCWrapperBuilder.swift @@ -79,6 +79,7 @@ class TemplateBasedCCWrapperBuilder: CCWrapperBuilder { /// Generates source of the cc wrapper + // swiftlint:disable line_length // swiftlint:disable:next function_body_length private func buildWrapperSource(clangCommand: String, markerFilename: String, commitSha: String) -> String { return """ @@ -516,5 +517,5 @@ class TemplateBasedCCWrapperBuilder: CCWrapperBuilder { #pragma GCC diagnostic pop } """ - } // swiftlint:disable:next file_length -} + } // swiftlint:disable:next file_length line_length +} // swiftlint:enable line_length diff --git a/Sources/XCRemoteCache/Commands/Prepare/Integrate/LLDBInitPatcher.swift b/Sources/XCRemoteCache/Commands/Prepare/Integrate/LLDBInitPatcher.swift index 71ae338..76c6b6c 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/Integrate/LLDBInitPatcher.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/Integrate/LLDBInitPatcher.swift @@ -56,7 +56,7 @@ class FileLLDBInitPatcher: LLDBInitPatcher { } private func findIndices(in collection: [String], value: String) -> [Int] { - collection.enumerated().reduce([]) { (result, line) -> [Int] in + collection.enumerated().reduce([]) { result, line -> [Int] in if line.element == Self.preambleString { return result + [line.offset] } @@ -75,7 +75,7 @@ class FileLLDBInitPatcher: LLDBInitPatcher { var contentLines = originalContentLines let preambleIndices = findIndices(in: contentLines, value: Self.preambleString) - if preambleIndices.count > 0 { + if !preambleIndices.isEmpty { let firstLLDBCommandIndex = preambleIndices[0] + 1 if firstLLDBCommandIndex >= contentLines.count { // corrupted file, append the script line at the bottom diff --git a/Sources/XCRemoteCache/Commands/Prepare/Integrate/XCIntegrate.swift b/Sources/XCRemoteCache/Commands/Prepare/Integrate/XCIntegrate.swift index 6fc952d..20bc9d0 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/Integrate/XCIntegrate.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/Integrate/XCIntegrate.swift @@ -64,6 +64,7 @@ public class XCIntegrate { self.output = output } + // swiftlint:disable:next function_body_length public func main() { do { let env = ProcessInfo.processInfo.environment @@ -114,7 +115,7 @@ public class XCIntegrate { let integrator = XcodeProjIntegrate( project: context.projectPath, - mode:context.mode, + mode: context.mode, binaries: context.binaries, configurationIncludeOracle: configurationOracle, targetIncludeOracle: targetOracle, diff --git a/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeProjIntegrate.swift b/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeProjIntegrate.swift index 04f6113..aaa561a 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeProjIntegrate.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeProjIntegrate.swift @@ -114,7 +114,9 @@ struct XcodeProjIntegrate: Integrate { markPhase = PBXShellScriptBuildPhase( name: "\(Self.BuildStepPrefix)RemoteCache_mark", inputPaths: [binaries.prepare.path], - shellScript: "\"$SCRIPT_INPUT_FILE_0\" mark --configuration \"$CONFIGURATION\" --platform \"$PLATFORM_NAME\"" + shellScript: + "\"$SCRIPT_INPUT_FILE_0\" mark " + + "--configuration \"$CONFIGURATION\" --platform \"$PLATFORM_NAME\"" ) } @@ -129,6 +131,7 @@ struct XcodeProjIntegrate: Integrate { try encodedYAML.write(to: configOverrideLocation, atomically: false, encoding: .utf8) } + // swiftlint:disable:next function_body_length func run() throws { let outputFile = output ?? projectURL let projectRoot = projectURL.deletingLastPathComponent() diff --git a/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeSettingsFlags.swift b/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeSettingsFlags.swift index 0ce7468..bdda790 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeSettingsFlags.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeSettingsFlags.swift @@ -100,7 +100,7 @@ struct XcodeSettingsCFlags: XcodeSettingsFlags { case (.some(let existing), _): var flagsComponents: [String] = existing.split(separator: " ").map(String.init) // remove (if exists) - let existingFlagIndex = flagsComponents.firstIndex { (component) -> Bool in + let existingFlagIndex = flagsComponents.firstIndex { component -> Bool in component.hasPrefix("\(Self.prefix)\(key)=") } if let index = existingFlagIndex { diff --git a/Sources/XCRemoteCache/Commands/Prepare/XCPrepareMark.swift b/Sources/XCRemoteCache/Commands/Prepare/XCPrepareMark.swift index b71c06a..d6c0ce4 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/XCPrepareMark.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/XCPrepareMark.swift @@ -38,6 +38,7 @@ public class XCPrepareMark { self.commit = commit } + // swiftlint:disable:next function_body_length public func main() { let env = ProcessInfo.processInfo.environment let fileManager = FileManager.default diff --git a/Sources/XCRemoteCache/Commands/Swiftc/XCSwiftc.swift b/Sources/XCRemoteCache/Commands/Swiftc/XCSwiftc.swift index d84152d..73976ae 100644 --- a/Sources/XCRemoteCache/Commands/Swiftc/XCSwiftc.swift +++ b/Sources/XCRemoteCache/Commands/Swiftc/XCSwiftc.swift @@ -101,7 +101,10 @@ public class XCSwiftc { objcHeaderOutput: context.objcHeaderOutput, diskCopier: HardLinkDiskCopier(fileManager: fileManager) ) - let allInvocationsStorage = ExistingFileStorage(storageFile: context.invocationHistoryFile, command: swiftcCommand) + let allInvocationsStorage = ExistingFileStorage( + storageFile: context.invocationHistoryFile, + command: swiftcCommand + ) // When fallbacking to local compilation do not call historical `swiftc` invocations // The current fallback invocation already compiles all files in a target let invocationStorage = FilteredInvocationStorage( diff --git a/Sources/XCRemoteCache/Config/XCRemoteCacheConfig.swift b/Sources/XCRemoteCache/Config/XCRemoteCacheConfig.swift index f116476..3b6b84b 100644 --- a/Sources/XCRemoteCache/Config/XCRemoteCacheConfig.swift +++ b/Sources/XCRemoteCache/Config/XCRemoteCacheConfig.swift @@ -94,10 +94,11 @@ public struct XCRemoteCacheConfig: Encodable { var focusedTargets: [String] = [] /// Disable cache for http requests to fecth metadata and download artifacts var disableHttpCache: Bool = false - /// Path, relative to $TARGET_TEMP_DIR which gathers all compilation commands that should be executed if a target - /// switches to local compilation. Example: A new `.swift` file invalidates remote artifact and triggers local compilation - /// When that happens, all previously skipped clang build steps need to be eventually called locally - this file lists - /// all these commands. + /// Path, relative to $TARGET_TEMP_DIR which gathers all compilation commands that should be e + /// xecuted if a target switches to local compilation. + /// Example: A new `.swift` file invalidates remote arXcodeProjIntegrate.swifttifact and triggers local compilation + /// When that happens, all previously skipped clang build steps + /// need to be eventually called locally - this file lists all these commands. var compilationHistoryFile: String = "history.compile" /// Timeout for remote response data interval (in seconds). If an interval between data chunks is /// longer than a timeout, a request fails @@ -124,6 +125,7 @@ public struct XCRemoteCacheConfig: Encodable { extension XCRemoteCacheConfig { /// Merges existing config with the other config and returns a final result /// `other` scheme overrides existing configuration + // swiftlint:disable:next function_body_length func merged(with scheme: ConfigFileScheme) -> XCRemoteCacheConfig { var merge = self merge.mode = scheme.mode ?? mode diff --git a/Sources/XCRemoteCache/Network/Authentication/AWSV4Signature.swift b/Sources/XCRemoteCache/Network/Authentication/AWSV4Signature.swift index 73ef708..00f522a 100644 --- a/Sources/XCRemoteCache/Network/Authentication/AWSV4Signature.swift +++ b/Sources/XCRemoteCache/Network/Authentication/AWSV4Signature.swift @@ -35,9 +35,22 @@ struct AWSV4Signature { request.setValue((request.httpBody ?? Data()).sha256(), forHTTPHeaderField: "x-amz-content-sha256") let canonicalRequest = CanonicalRequest(request: request) - let stringToSign = StringToSign(region: region, service: service, canonicalRequestHash: canonicalRequest.hash, date: date) - let awsV4SigningKey = AWSV4SigningKey(secretAccessKey: secretKey, region: region, service: service, date: date) - let signature = HMAC.calcHMAC(keyArray: awsV4SigningKey.value, value: stringToSign.value).map { String(format: "%02hhx", $0) }.joined() + let stringToSign = StringToSign( + region: region, + service: service, + canonicalRequestHash: canonicalRequest.hash, + date: date + ) + let awsV4SigningKey = AWSV4SigningKey( + secretAccessKey: secretKey, + region: region, + service: service, + date: date + ) + let signature = HMAC.calcHMAC( + keyArray: awsV4SigningKey.value, + value: stringToSign.value + ).map { String(format: "%02hhx", $0) }.joined() let authValue = "AWS4-HMAC-SHA256 " + diff --git a/Sources/XCRemoteCache/Network/Authentication/HMAC.swift b/Sources/XCRemoteCache/Network/Authentication/HMAC.swift index 15eb943..57d0880 100644 --- a/Sources/XCRemoteCache/Network/Authentication/HMAC.swift +++ b/Sources/XCRemoteCache/Network/Authentication/HMAC.swift @@ -52,7 +52,14 @@ struct HMAC { private static func calcHMAC(keyUnsafeBytes: UnsafeRawBufferPointer, value: String, out: UnsafeMutableRawPointer!) { value.data(using: .utf8)!.withUnsafeBytes { value in - CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyUnsafeBytes.baseAddress, Int(keyUnsafeBytes.count), value.baseAddress, Int(value.count), out) + CCHmac( + CCHmacAlgorithm(kCCHmacAlgSHA256), + keyUnsafeBytes.baseAddress, + Int(keyUnsafeBytes.count), + value.baseAddress, + Int(value.count), + out + ) } } } diff --git a/Sources/XCRemoteCache/Stats/CacheHitLogger.swift b/Sources/XCRemoteCache/Stats/CacheHitLogger.swift index 213f054..8f276e1 100644 --- a/Sources/XCRemoteCache/Stats/CacheHitLogger.swift +++ b/Sources/XCRemoteCache/Stats/CacheHitLogger.swift @@ -28,8 +28,8 @@ protocol CacheHitLogger { /// Logs target hit or miss, based on an action of a build class ActionSpecificCacheHitLogger: CacheHitLogger { private let statsLogger: StatsLogger - private let hitCounter: XCRemoteCacheStatistics.Counter - private let missCounter: XCRemoteCacheStatistics.Counter + private let hitCounter: XCRemoteCacheStatistics.Counter? + private let missCounter: XCRemoteCacheStatistics.Counter? init(action: BuildActionType, statsLogger: StatsLogger) { self.statsLogger = statsLogger @@ -37,19 +37,24 @@ class ActionSpecificCacheHitLogger: CacheHitLogger { case .index: hitCounter = .indexingTargetHitCount missCounter = .indexingTargetMissCount - case .unknown: - fallthrough case .build: hitCounter = .targetCacheHit missCounter = .targetCacheMiss + case .unknown: + hitCounter = nil + missCounter = nil } } func logHit() throws { - try statsLogger.log(hitCounter) + if let hitCounter = hitCounter { + try statsLogger.log(hitCounter) + } } func logMiss() throws { - try statsLogger.log(missCounter) + if let missCounter = missCounter { + try statsLogger.log(missCounter) + } } } diff --git a/Tests/XCRemoteCacheTests/Artifacts/ArtifactSwiftProductsBuilderImplTests.swift b/Tests/XCRemoteCacheTests/Artifacts/ArtifactSwiftProductsBuilderImplTests.swift index ffaeac5..9fa5769 100644 --- a/Tests/XCRemoteCacheTests/Artifacts/ArtifactSwiftProductsBuilderImplTests.swift +++ b/Tests/XCRemoteCacheTests/Artifacts/ArtifactSwiftProductsBuilderImplTests.swift @@ -31,6 +31,7 @@ class ArtifactSwiftProductsBuilderImplTests: FileXCTestCase { private var builder: ArtifactSwiftProductsBuilderImpl! override func setUpWithError() throws { + try super.setUpWithError() let rootDir = try prepareTempDir() moduleDir = rootDir.appendingPathComponent("Products") swiftmoduleFile = moduleDir.appendingPathComponent("MyModule.swiftmodule") @@ -47,24 +48,41 @@ class ArtifactSwiftProductsBuilderImplTests: FileXCTestCase { func testIncludesRequiredSwiftmoduleFiles() throws { try fileManager.spt_createFile(swiftmoduleFile, content: "swiftmodule") try fileManager.spt_createFile(swiftmoduleDocFile, content: "swiftdoc") - let builderSwiftmoduleDir = builder.buildingArtifactSwiftModulesLocation().appendingPathComponent("arm64") - let expectedBuildedSwiftmoduleFile = builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftmodule") - let expectedBuildedSwiftmoduledocFile = builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftdoc") + let builderSwiftmoduleDir = + builder + .buildingArtifactSwiftModulesLocation() + .appendingPathComponent("arm64") + let expectedBuildedSwiftmoduleFile = + builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftmodule") + let expectedBuildedSwiftmoduledocFile = + builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftdoc") try builder.includeModuleDefinitionsToTheArtifact(arch: "arm64", moduleURL: swiftmoduleFile) - XCTAssertEqual(fileManager.contents(atPath: expectedBuildedSwiftmoduleFile.path), "swiftmodule".data(using: .utf8)) - XCTAssertEqual(fileManager.contents(atPath: expectedBuildedSwiftmoduledocFile.path), "swiftdoc".data(using: .utf8)) + XCTAssertEqual( + fileManager.contents(atPath: expectedBuildedSwiftmoduleFile.path), + "swiftmodule".data(using: .utf8) + ) + XCTAssertEqual( + fileManager.contents(atPath: expectedBuildedSwiftmoduledocFile.path), + "swiftdoc".data(using: .utf8) + ) } func testIncludesAllSwiftmoduleFiles() throws { try fileManager.spt_createEmptyFile(swiftmoduleFile) try fileManager.spt_createEmptyFile(swiftmoduleDocFile) try fileManager.spt_createEmptyFile(swiftmoduleSourceInfoFile) - let builderSwiftmoduleDir = builder.buildingArtifactSwiftModulesLocation().appendingPathComponent("arm64") - let expectedBuildedSwiftmoduleFile = builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftmodule") - let expectedBuildedSwiftmoduledocFile = builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftdoc") - let expectedBuildedSwiftSourceInfoFile = builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftsourceinfo") + let builderSwiftmoduleDir = + builder + .buildingArtifactSwiftModulesLocation() + .appendingPathComponent("arm64") + let expectedBuildedSwiftmoduleFile = + builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftmodule") + let expectedBuildedSwiftmoduledocFile = + builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftdoc") + let expectedBuildedSwiftSourceInfoFile = + builderSwiftmoduleDir.appendingPathComponent("MyModule.swiftsourceinfo") try builder.includeModuleDefinitionsToTheArtifact(arch: "arm64", moduleURL: swiftmoduleFile) @@ -74,6 +92,11 @@ class ArtifactSwiftProductsBuilderImplTests: FileXCTestCase { } func testFailsIncludingWhenMissingRequiredSwiftmoduleFiles() throws { - XCTAssertThrowsError(try builder.includeModuleDefinitionsToTheArtifact(arch: "arm64", moduleURL: swiftmoduleFile)) + XCTAssertThrowsError( + try builder.includeModuleDefinitionsToTheArtifact( + arch: "arm64", + moduleURL: swiftmoduleFile + ) + ) } } diff --git a/Tests/XCRemoteCacheTests/Commands/Prepare/Integrate/FileLLDBInitPatcherTests.swift b/Tests/XCRemoteCacheTests/Commands/Prepare/Integrate/FileLLDBInitPatcherTests.swift index 747a028..f1fca84 100644 --- a/Tests/XCRemoteCacheTests/Commands/Prepare/Integrate/FileLLDBInitPatcherTests.swift +++ b/Tests/XCRemoteCacheTests/Commands/Prepare/Integrate/FileLLDBInitPatcherTests.swift @@ -28,6 +28,7 @@ class FileLLDBInitPatcherTests: XCTestCase { private var patcher: FileLLDBInitPatcher! override func setUp() { + super.setUp() accessor = FileAccessorFake(mode: .normal) patcher = FileLLDBInitPatcher( file: lldbInitPath, diff --git a/Tests/XCRemoteCacheTests/Commands/SwiftcFilemapInputEditorTests.swift b/Tests/XCRemoteCacheTests/Commands/SwiftcFilemapInputEditorTests.swift index c73a945..80b2eb1 100644 --- a/Tests/XCRemoteCacheTests/Commands/SwiftcFilemapInputEditorTests.swift +++ b/Tests/XCRemoteCacheTests/Commands/SwiftcFilemapInputEditorTests.swift @@ -21,8 +21,8 @@ import XCTest class SwiftcFilemapInputEditorTests: FileXCTestCase { - - private let sampleInfo = SwiftCompilationInfo(info: SwiftModuleCompilationInfo( + private let sampleInfo = SwiftCompilationInfo( + info: SwiftModuleCompilationInfo( dependencies: nil, swiftDependencies: "/" ), files: []) @@ -65,17 +65,19 @@ class SwiftcFilemapInputEditorTests: FileXCTestCase { } } """#.data(using: .utf8)! - let expectedInfo = SwiftCompilationInfo(info: SwiftModuleCompilationInfo( - dependencies: "/master.d", - swiftDependencies: "/master.swiftdeps" - ), files: [ - SwiftFileCompilationInfo( - file: "/file1.swift", - dependencies: "/file1.d", - object: "/file1.o", - swiftDependencies: "/file1.swiftdeps" + let expectedInfo = SwiftCompilationInfo( + info: SwiftModuleCompilationInfo( + dependencies: "/master.d", + swiftDependencies: "/master.swiftdeps" ), - ]) + files: [ + SwiftFileCompilationInfo( + file: "/file1.swift", + dependencies: "/file1.d", + object: "/file1.o", + swiftDependencies: "/file1.swiftdeps" + ), + ]) try fileManager.spt_writeToFile(atPath: inputFile.path, contents: infoContentData) let readInfo = try editor.read() @@ -93,17 +95,18 @@ class SwiftcFilemapInputEditorTests: FileXCTestCase { } func testWritingSavesContentWithOptionalParameters() throws { - let extendedInfo = SwiftCompilationInfo(info: SwiftModuleCompilationInfo( - dependencies: "/master.d", - swiftDependencies: "/master.swiftdeps" - ), files: [ - SwiftFileCompilationInfo( - file: "/file1.swift", - dependencies: "/file1.d", - object: "/file1.o", - swiftDependencies: "/file1.swiftdeps" - ), - ]) + let extendedInfo = SwiftCompilationInfo( + info: SwiftModuleCompilationInfo( + dependencies: "/master.d", + swiftDependencies: "/master.swiftdeps" + ), files: [ + SwiftFileCompilationInfo( + file: "/file1.swift", + dependencies: "/file1.d", + object: "/file1.o", + swiftDependencies: "/file1.swiftdeps" + ), + ]) try editor.write(extendedInfo) diff --git a/Tests/XCRemoteCacheTests/Commands/SwiftcTests.swift b/Tests/XCRemoteCacheTests/Commands/SwiftcTests.swift index f2ea5e5..55c888c 100644 --- a/Tests/XCRemoteCacheTests/Commands/SwiftcTests.swift +++ b/Tests/XCRemoteCacheTests/Commands/SwiftcTests.swift @@ -277,7 +277,9 @@ class SwiftcTests: FileXCTestCase { let artifactObjCHeader = URL(fileURLWithPath: "/cachedArtifact/include/archTest/Target-Swift.h") let artifactSwiftmodule = URL(fileURLWithPath: "/cachedArtifact/swiftmodule/archTest/Target.swiftmodule") let artifactSwiftdoc = URL(fileURLWithPath: "/cachedArtifact/swiftmodule/archTest/Target.swiftdoc") - let artifactSwiftSourceInfo = URL(fileURLWithPath: "/cachedArtifact/swiftmodule/archTest/Target.swiftsourceinfo") + let artifactSwiftSourceInfo = URL( + fileURLWithPath: "/cachedArtifact/swiftmodule/archTest/Target.swiftsourceinfo" + ) artifactOrganizer = ArtifactOrganizerFake(artifactRoot: artifactRoot) let swiftc = Swiftc( @@ -457,5 +459,5 @@ class SwiftcTests: FileXCTestCase { ) XCTAssertNoThrow(try swiftc.mockCompilation()) - } + } // swiftlint:disable:next file_length } diff --git a/Tests/XCRemoteCacheTests/Dependencies/FileFingerprintSyncerTests.swift b/Tests/XCRemoteCacheTests/Dependencies/FileFingerprintSyncerTests.swift index ff5e02b..043d56b 100644 --- a/Tests/XCRemoteCacheTests/Dependencies/FileFingerprintSyncerTests.swift +++ b/Tests/XCRemoteCacheTests/Dependencies/FileFingerprintSyncerTests.swift @@ -27,6 +27,7 @@ class FileFingerprintSyncerTests: FileXCTestCase { private var swiftmoduleDir: URL! override func setUpWithError() throws { + try super.setUpWithError() syncer = FileFingerprintSyncer( fingerprintOverrideExtension: "md5", dirAccessor: fileManager, diff --git a/Tests/XCRemoteCacheTests/Dependencies/TargetDependenciesReaderTests.swift b/Tests/XCRemoteCacheTests/Dependencies/TargetDependenciesReaderTests.swift index 2830047..0437a92 100644 --- a/Tests/XCRemoteCacheTests/Dependencies/TargetDependenciesReaderTests.swift +++ b/Tests/XCRemoteCacheTests/Dependencies/TargetDependenciesReaderTests.swift @@ -27,6 +27,7 @@ class TargetDependenciesReaderTests: XCTestCase { private var reader: TargetDependenciesReader! override func setUp() { + super.setUp() dirAccessor = DirAccessorFake() /// A Factory that builds a faked dependency reader that returns a single dependency, /// a basename of the input .d file and the ".swift" extension diff --git a/Tests/XCRemoteCacheTests/FileAccess/Copier/CopyDiskCopierTests.swift b/Tests/XCRemoteCacheTests/FileAccess/Copier/CopyDiskCopierTests.swift index 7bbf7b1..c4b567a 100644 --- a/Tests/XCRemoteCacheTests/FileAccess/Copier/CopyDiskCopierTests.swift +++ b/Tests/XCRemoteCacheTests/FileAccess/Copier/CopyDiskCopierTests.swift @@ -27,6 +27,7 @@ class CopyDiskCopierTests: FileXCTestCase { private var emptySourceFile: URL! override func setUpWithError() throws { + try super.setUpWithError() workingDir = try prepareTempDir() emptySourceFile = workingDir.appendingPathComponent("source") try fileManager.spt_writeToFile(atPath: emptySourceFile.path, contents: Data()) diff --git a/Tests/XCRemoteCacheTests/Output/FilteredInvocationStorageTests.swift b/Tests/XCRemoteCacheTests/Output/FilteredInvocationStorageTests.swift index 22e5838..2536c45 100644 --- a/Tests/XCRemoteCacheTests/Output/FilteredInvocationStorageTests.swift +++ b/Tests/XCRemoteCacheTests/Output/FilteredInvocationStorageTests.swift @@ -26,6 +26,7 @@ class FilteredInvocationStorageTests: XCTestCase { var storage: FilteredInvocationStorage! override func setUp() { + super.setUp() storage = FilteredInvocationStorage(storage: underlyingStorage, retrieveIgnoredCommands: ["to_ignore"]) } diff --git a/Tests/XCRemoteCacheTests/Output/InvocationFileStorageTests.swift b/Tests/XCRemoteCacheTests/Output/InvocationFileStorageTests.swift index 655873b..383ff3a 100644 --- a/Tests/XCRemoteCacheTests/Output/InvocationFileStorageTests.swift +++ b/Tests/XCRemoteCacheTests/Output/InvocationFileStorageTests.swift @@ -28,6 +28,7 @@ class InvocationFileStorageTests: FileXCTestCase { private var storage: ExistingFileStorage! override func setUpWithError() throws { + try super.setUpWithError() file = try prepareTempDir().appendingPathComponent("file.history") try fileManager.spt_createEmptyFile(file) storage = ExistingFileStorage(storageFile: file, command: command) diff --git a/Tests/XCRemoteCacheTests/Stats/ActionSpecificCacheHitLoggerTests.swift b/Tests/XCRemoteCacheTests/Stats/ActionSpecificCacheHitLoggerTests.swift index e9d2824..bf0566a 100644 --- a/Tests/XCRemoteCacheTests/Stats/ActionSpecificCacheHitLoggerTests.swift +++ b/Tests/XCRemoteCacheTests/Stats/ActionSpecificCacheHitLoggerTests.swift @@ -25,6 +25,7 @@ class ActionSpecificCacheHitLoggerTests: FileXCTestCase { private var coordinator: StatsCoordinator! override func setUp() { + super.setUp() coordinator = InMemoryStatsCoordinator() }