class Fastlane::SwiftRunnerUpgrader
build project
Constants
- API_VERSION_REGEX
- RELATIVE_SOURCE_FILE_PATH
Attributes
Public Class Methods
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 28 def initialize @source_swift_code_file_folder_path = File.expand_path(File.join(Fastlane::ROOT, "/swift")) @target_swift_code_file_folder_path = FastlaneCore::FastlaneFolder.swift_folder_path Fastlane::Setup.setup_swift_support manifest_file = File.join(@source_swift_code_file_folder_path, "/upgrade_manifest.json") UI.success("loading manifest: #{manifest_file}") @manifest_hash = JSON.parse(File.read(manifest_file)) @manifest_groups = @manifest_hash.values.uniq runner_project_path = FastlaneCore::FastlaneFolder.swift_runner_project_path @target_project = Xcodeproj::Project.open(runner_project_path) @root_group = @target_project.groups.select { |group| group.name == "Fastlane Runner" }.first @fastlane_runner_target = @target_project.targets.select { |target| target.name == "FastlaneRunner" }.first end
Public Instance Methods
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 233 def add_missing_copy_phase!(dry_run: false) # Check if upgrade is needed # Check if Copy Files build phase contains FastlaneRunner target. phase_copy_sign = self.fastlane_runner_target.copy_files_build_phases.map(&:files).flatten.select { |file| file.display_name == "FastlaneRunner" }.first # If fastlane copy files build phase exists already, we don't need any more changes to the Xcode project phase_copy_sign = self.fastlane_runner_target.copy_files_build_phases.select { |phase_copy| phase_copy.name == "FastlaneRunnerCopySigned" }.first unless phase_copy_sign return true if dry_run && phase_copy_sign.nil? return false if dry_run # Proceed to upgrade old_phase_copy_sign = self.fastlane_runner_target.shell_script_build_phases.select { |phase_copy| phase_copy.shell_script == "cd \"${SRCROOT}\"\ncd ../..\ncp \"${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}\" .\n" }.first old_phase_copy_sign.remove_from_project unless old_phase_copy_sign.nil? unless phase_copy_sign # Create a copy files build phase phase_copy_sign = self.fastlane_runner_target.new_copy_files_build_phase("FastlaneRunnerCopySigned") phase_copy_sign.dst_path = "$SRCROOT/../.." phase_copy_sign.dst_subfolder_spec = "0" phase_copy_sign.run_only_for_deployment_postprocessing = "0" targetBinaryReference = self.fastlane_runner_target.product_reference phase_copy_sign.add_file_reference(targetBinaryReference) # Set "Code sign on copy" flag on Xcode for fastlane_runner_target targetBinaryReference.build_files.each { |target_binary_build_file_reference| target_binary_build_file_reference.settings = { "ATTRIBUTES": ["CodeSignOnCopy"] } } end target_project.save end
adds new copy files build phase to fastlane_runner_target
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 215 def add_missing_flags!(dry_run: false) # Check if upgrade is needed # If fastlane build settings exists already, we don't need any more changes to the Xcode project self.fastlane_runner_target.build_configurations.each { |config| return true if dry_run && config.build_settings["CODE_SIGN_IDENTITY"].nil? return true if dry_run && config.build_settings["MACOSX_DEPLOYMENT_TARGET"].nil? } return false if dry_run # Proceed to upgrade self.fastlane_runner_target.build_configurations.each { |config| config.build_settings["CODE_SIGN_IDENTITY"] = "-" config.build_settings["MACOSX_DEPLOYMENT_TARGET"] = "10.12" } target_project.save end
adds build_settings flags to fastlane_runner_target
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 186 def add_missing_groups_and_files!(dry_run: false) missing_groups = self.find_missing_groups.to_set unless missing_groups.length > 0 UI.verbose("No missing groups found, so we don't need to worry about adding new groups") return false end # well, we know we have some changes to make, so if this is a dry run, # don't bother doing anything and just return true return true if dry_run missing_groups.each do |missing_group_name| new_group = @root_group.new_group(missing_group_name) # find every file in the manifest that belongs to the new group, and add it to the new group self.manifest_hash.each do |filename, group| next unless group.casecmp(missing_group_name.downcase).zero? # assumes this is a new file, we don't handle moving files between groups new_file_reference = new_group.new_file("#{RELATIVE_SOURCE_FILE_PATH}#{filename}") # add references to the target, and make sure they are added to the build phase to self.fastlane_runner_target.source_build_phase.add_file_reference(new_file_reference) end end return true # yup, we definitely updated groups end
adds new groups, and the files inside those groups Note: this does not add new files to existing groups, that is in add_new_files_to_groups!
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 138 def add_new_files_to_groups! inverted_hash = {} # need {group => [file1, file2, etc..]} instead of: {file1 => group, file2 => group, etc...} self.manifest_hash.each do |filename, group_name| group_name = group_name.downcase files_in_group = inverted_hash[group_name] if files_in_group.nil? files_in_group = [] inverted_hash[group_name] = files_in_group end files_in_group << filename end # this helps us signal to the user that we made changes updated_project = false # iterate through the groups and collect all the swift files in each @root_group.groups.each do |group| # current group's filenames existing_group_files_set = group.files .select { |file| !file.name.nil? && file.name.end_with?(".swift") } .map(&:name) .to_set group_name = group.name.downcase manifest_group_filenames = inverted_hash[group_name] # compare the current group files to what the manifest says should minimally be there manifest_group_filenames.each do |filename| # current group is missing a file from the manifest, need to add it next if existing_group_files_set.include?(filename) UI.verbose("Adding new file #{filename} to group: `#{group.name}`") new_file_reference = group.new_file("#{RELATIVE_SOURCE_FILE_PATH}#{filename}") # add references to the target, and make sure they are added to the build phase to self.fastlane_runner_target.source_build_phase.add_file_reference(new_file_reference) updated_project = true end end return updated_project end
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 118 def copy_file_if_needed!(filename: nil, dry_run: false) needs_update = file_needs_update?(filename: filename) UI.verbose("file #{filename} needs an update") if needs_update # Ok, we know if this file needs an update, can return now if it's a dry run return needs_update if dry_run unless needs_update # no work needed, just return return false end source = File.join(self.source_swift_code_file_folder_path, "/#{filename}") target = File.join(self.target_swift_code_file_folder_path, "/#{filename}") FileUtils.cp(source, target) UI.verbose("Copied #{source} to #{target}") return true end
currently just copies file, even if not needed.
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 84 def file_needs_update?(filename: nil) # looking for something like: FastlaneRunnerAPIVersion [0.9.1] regex_to_use = API_VERSION_REGEX source = File.join(self.source_swift_code_file_folder_path, "/#{filename}") target = File.join(self.target_swift_code_file_folder_path, "/#{filename}") # target doesn't have the file yet, so ya, I'd say it needs to be updated return true unless File.exist?(target) source_file_content = File.read(source) target_file_content = File.read(target) # ignore if files don't contain FastlaneRunnerAPIVersion return false unless source_file_content.include?("FastlaneRunnerAPIVersion") return false unless target_file_content.include?("FastlaneRunnerAPIVersion") bundled_version = source_file_content.match(regex_to_use)[1] target_version = target_file_content.match(regex_to_use)[1] file_versions_are_different = bundled_version != target_version UI.verbose("#{filename} FastlaneRunnerAPIVersion (bundled/target): #{bundled_version}/#{target_version}") files_are_different = source_file_content != target_file_content if files_are_different && !file_versions_are_different UI.verbose("File versions are the same, but the two files are not equal, so that's a problem, setting needs update to 'true'") end needs_update = file_versions_are_different || files_are_different return needs_update end
compares source file against the target file’s FastlaneRunnerAPIVersion and returned ‘true` if there is a difference
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 71 def find_missing_groups missing_groups = [] existing_group_names_set = @root_group.groups.map { |group| group.name.downcase }.to_set self.manifest_groups.each do |group_name| unless existing_group_names_set.include?(group_name.downcase) missing_groups << group_name end end return missing_groups end
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 63 def upgrade_files!(dry_run: false) upgraded_anything = false self.manifest_hash.each do |filename, group| upgraded_anything = copy_file_if_needed!(filename: filename, dry_run: dry_run) || upgraded_anything end return upgraded_anything end
Source
# File fastlane/lib/fastlane/swift_runner_upgrader.rb, line 47 def upgrade_if_needed!(dry_run: false) upgraded = add_missing_flags!(dry_run: dry_run) upgraded = add_missing_copy_phase!(dry_run: dry_run) || upgraded upgraded = add_missing_groups_and_files!(dry_run: dry_run) || upgraded upgraded = upgrade_files!(dry_run: dry_run) || upgraded upgraded = add_new_files_to_groups! || upgraded UI.verbose("FastlaneRunner project has been updated and can be written back to disk") if upgraded unless dry_run UI.verbose("FastlaneRunner project changes have been stored") if upgraded target_project.save if upgraded end return upgraded end