b0VIM 8.0xM\;7+joshJoshs-MBP~josh/Projects/fastlane/fastlane/fastlane_core/lib/fastlane_core/project.rbutf-8 3210#"! Utpj pm rKzODOOad#jgU;j^]*) Q + U , g Y M L  B  ` L ; {maWON*on2baYnd\[H0('qg_^ )  # # XcodePro # so there is no need to manually ca # so there is no need to manually call @workspace.load_schemes(path) # XcodeProject::Workspace automati # so there is no need to manually call @workspace.load_schemes(path) return nil unless workspace? def workspace # returns the Xcodeproj::Workspace or nil if it is a project end end return File.basename(options[:project], ".xcodeproj") else return File.basename(options[:workspace], ".xcworkspace") if is_workspace def project_name end self.is_workspace def workspace? end end UI.user_error!("Could not find project at path '#{path}'") if !path || !File.directory?(path) self.xcodebuild_suppress_stderr = xcodebuild_suppress_stderr self.xcodebuild_list_silent = xcodebuild_list_silent self.is_workspace = (options[:workspace].to_s.length > 0) self.path = File.expand_path(options[:workspace] || options[:project]) self.options = options def initialize(options, xcodebuild_list_silent: false, xcodebuild_suppress_stderr: false) attr_accessor :xcodebuild_suppress_stderr # Gets rid of annoying plugin info warnings. # Should we redirect stderr to /dev/null for xcodebuild commands? attr_accessor :xcodebuild_list_silent # Should the output of xcodebuild commands be silenced? attr_accessor :options # The config object containing the scheme, configuration, etc. attr_accessor :is_workspace # Is this project a workspace? attr_accessor :path # Path to the project/workspace end end end end UI.error("Couldn't find project at path '#{File.expand_path(path)}'") else end UI.error("Path must end with either .xcworkspace or .xcodeproj") else break config[:project] = path elsif path.end_with?(".xcodeproj") break config[:workspace] = path if path.end_with?(".xcworkspace") if File.directory?(path) path = UI.input("Couldn't automatically detect the project file, please provide a path: ") loop do def select_project(config) end end select_project(config) if config[:workspace].nil? && config[:project].nil? end end config[:project] = project.first elsif !project.first.nil? config[:project] = choose(*project) puts("Select Project: ") if project.count > 1 project = Dir["./*.xcodeproj"] if config[:workspace].to_s.length == 0 && config[:project].to_s.length == 0 return if config[:workspace].to_s.length > 0 end end config[:workspace] = workspace.first elsif !workspace.first.nil? config[:workspace] = choose(*workspace) puts("Select Workspace: ") if workspace.count > 1 workspace = Dir["./*.xcworkspace"] if config[:workspace].to_s.length == 0 return if config[:project].to_s.length > 0 end UI.user_error!("You can only pass either a workspace or a project path, not both") if config[:workspace].to_s.length > 0 && config[:project].to_s.length > 0 def detect_projects(config) # Project discovery class << self class Project # rubocop:disable Metrics/ClassLength # Represents an Xcode projectmodule FastlaneCorerequire 'xcodeproj'require_relative 'helper'adiOckSR/. . c b z y V U D !   z J 1 d , 0/: wOE=<0/{smihend end end FastlaneCore::Env.truthy?("AUTOMATED_SCHEME_SELECTION") def automated_scheme_selection? # matching project name? # If scheme not specified, do we want the scheme private end end return @_project_paths = [path] # Return the path as an array else return @_project_paths end current_match.end_with?("Pods/Pods.xcodeproj") # We're not interested in a `Pods` project, as it doesn't contain any relevant information about code signing end.reject do |current_match| current_match.end_with?(".xcodeproj") # Xcode workspaces can contain loose files now, so let's filter non-xcodeproj files. @_project_paths = file_references_paths.select do |current_match| file_references_paths = workspace.file_references.map { |fr| fr.absolute_path(workspace_dir_path) } workspace_dir_path = File.expand_path("..", self.path) # for details see https://github.com/CocoaPods/Xcodeproj/blob/e0287156d426ba588c9234bb2a4c824149889860/lib/xcodeproj/workspace/file_reference.rb``` # * handle different types (group:, container: etc.) of file references and their paths # * parse the contents.xcworkspacedata XML file # Use Xcodeproj gem here to # We have a reference to the workspace, let's find the xcodeproj file # Find the xcodeproj file, as the information isn't included in the workspace file if self.workspace? return @_project_paths if @_project_paths def project_paths # (might be multiple, because of workspaces) # Array of paths to all project files end return result end retry try_timeout = next_timeout try += 1 raise if try_limit_reached UI.important(message) message += ", trying again with a #{next_timeout} second timeout..." unless try_limit_reached message = "Command timed out after #{try_timeout} seconds on try #{try} of #{total_tries}" next_timeout = try_timeout * 2 # Try harder on each iteration try_limit_reached = try >= total_tries rescue Timeout::Error end result = `#{command}`.to_s # Using Helper.backticks didn't work here. `Timeout` doesn't time out, and the command hangs forever Timeout.timeout(try_timeout) do begin try_timeout = timeout try = 1 total_tries = retries + 1 result = '' UI.command(command) if print require 'timeout' def self.run_command(command, timeout: 0, retries: 0, print: true) # - retry feature added to solve https://github.com/fastlane/fastlane/issues/4059 # Note: - currently affected by https://github.com/fastlane/fastlane/issues/1504 # @returns the output of the command # @raises Timeout::Error if all tries result in a timeout # a doubling of the previous timeout has elapsed.ad+K}L" ~ r h g 6 5  9 - , | ,  I y R Q &    nmV.^4oIe>jba+ # Returns bundle_id and sets the scheme for xcrun end end project.build_configurations.map(&:name) else .map(&:name) .compact .flatten end end [] rescue Xcodeproj::Project.open(p).build_configurations begin # workspaces. # silently ignore non-existent projects from # To maintain backwards compatibility, we .map do |p| .reject { |p| p.include?("Pods/Pods.xcodeproj") } .map(&:path) .file_references workspace @configurations ||= if workspace? def configurations # Get all available configurations in an array end UI.error("Afterwards make sure to commit the changes into version control") UI.error("Open Xcode, click on `Manage Schemes` and check the `Shared` box for the schemes you want to use") UI.error("Couldn't find any schemes in this project, make sure that the scheme is shared if you are using a workspace") def show_scheme_shared_information end end UI.user_error!("No Schemes found") show_scheme_shared_information else end options[:scheme] = choose(*schemes) puts("Select Scheme: ") else UI.user_error!("Multiple schemes found") show_scheme_shared_information UI.error("Since this is a CI, please pass one using the `scheme` option") UI.error("Multiple schemes found but you haven't specified one.") elsif Helper.ci? options[:scheme] = project_name UI.important("Using scheme matching project name (#{project_name}).") elsif automated_scheme_selection? && schemes.include?(project_name) options[:scheme] = preferred.last if preferred_to_include && preferred.count == 1 end preferred = schemes.find_all { |a| a.downcase.include?(preferred_to_include.downcase) } if preferred_to_include preferred = nil elsif schemes.count > 1 options[:scheme] = schemes.last if schemes.count == 1 return if options[:scheme].to_s.length > 0 end end options[:scheme] = nil UI.error("Couldn't find specified scheme '#{options[:scheme]}'. Please make sure that the scheme is shared, see https://developer.apple.com/library/content/documentation/IDEs/Conceptual/xcode_guide-continuous_integration/ConfigureBots.html#//apple_ref/doc/uid/TP40013292-CH9-SW3") unless schemes.include?(options[:scheme].to_s) # Verify the scheme is available if options[:scheme].to_s.length > 0 def select_scheme(preferred_to_include: nil) # Use a scheme containing the preferred_to_include string when multiple schemes were found # Let the user select a schemeadm i1uml@. ^ 7 U  i a  a 5 o V ZM+Yh uFW d=Y: # Returns bundle_id and sets the scheme for xcrun end end project.build_configurations.map(&:name) else .map(&:name) .compact .flatten end end [] rescue Xcodeproj::Project.open(p).build_configurations begin # workspaces. # silently ignore non-existent projects from # To maintain backwards compatibility, we .map do |p| .reject { |p| p.include?("Pods/Pods.xcodeproj") } .map(&:path) .file_references workspace @configurations ||= if workspace? def configurations # Get all available configurations in an array end UI.error("Afterwards make sure to commit the changes into version control") UI.error("Open Xcode, click on `Manage Schemes` and check the `Shared` box for the schemes you want to use") UI.error("Couldn't find any schemes in this project, make sure that the scheme is shared if you are using a workspace") def show_scheme_shared_information end end UI.user_error!("No Schemes found") show_scheme_shared_information else end options[:scheme] = choose(*schemes) puts("Select Scheme: ") else UI.user_error!("Multiple schemes found") show_scheme_shared_information UI.error("Since this is a CI, please pass one using the `scheme` option") UI.error("Multiple schemes found but you haven't specified one.") elsif Helper.ci? options[:scheme] = project_name UI.important("Using scheme matching project name (#{project_name}).") elsif automated_scheme_selection? && schemes.include?(project_name) options[:scheme] = preferred.last if preferred_to_include && preferred.count == 1 end preferred = schemes.find_all { |a| a.downcase.include?(preferred_to_include.downcase) } if preferred_to_include preferred = nil elsif schemes.count > 1 end end Xcodeproj::Project.schemes(path).map else end scheme_path UI.verbose("the scheme_path: #{scheme_path}") scheme_path = File.join(shared_data_path, "#{k}.xcscheme") shared_data_path = Xcodeproj::XCScheme.shared_data_dir(v) UI.verbose("making with #{k} and #{v}") end.map do |k, v| v.include?("Pods/Pods.xcodeproj") workspace.schemes.reject do |k, v| @xcschemes ||= if workspace? UI.verbose("workspace schemes: #{workspace.schemes}") def xcschemes # Get all available schemes in an array end end Xcodeproj::Project.schemes(path) else end.keys v.include?("Pods/Pods.xcodeproj") workspace.schemes.reject do |k, v| @schemes ||= if workspace? def schemes # Get all available schemes in an array end @project ||= Xcodeproj::Project.open(path)adEIzdK5tCB [ S R : / ' &  ; 3 2   8 0 /  w o n Y l ^VU9Q;1[#t(x&%  }|IH def build_xcodebuild_showbuildsettings_command ##################################################### # @!group Raw Access ##################################################### end return proj proj << "-xcconfig #{options[:xcconfig].shellescape}" if options[:xcconfig] proj << "-configuration #{options[:configuration].shellescape}" if options[:configuration] proj << "-project #{options[:project].shellescape}" if options[:project] proj << "-scheme #{options[:scheme].shellescape}" if options[:scheme] proj << "-workspace #{options[:workspace].shellescape}" if options[:workspace] proj = [] def xcodebuild_parameters end end.uniq.compact end when "appletvsimulator", "appletvos" then :tvOS when "watchsimulator", "watchos" then :watchOS when "iphonesimulator", "iphoneos" then :iOS when "macosx" then :macOS case platform supported_platforms.split.map do |platform| end return [:iOS] UI.important("Could not read the \"SUPPORTED_PLATFORMS\" build setting, assuming that the project supports iOS only.") if supported_platforms.nil? supported_platforms = build_settings(key: "SUPPORTED_PLATFORMS") def supported_platforms end supported_platforms.include?(:iOS) def ios? end supported_platforms.include?(:tvOS) def tvos? end supported_platforms.include?(:macOS) def mac? end (build_settings(key: "PRODUCT_TYPE") == "com.apple.product-type.tool") def command_line_tool? end (framework? && build_settings(key: "PLATFORM_NAME") == "macosx") def mac_framework? end ((dynamic_library? or static_library?) && build_settings(key: "PLATFORM_NAME") == "macosx") def mac_library? end (application? && build_settings(key: "PLATFORM_NAME") == "macosx") def mac_app? end !(framework? || static_library? || dynamic_library?) def produces_archive? end (application? && build_settings(key: "PLATFORM_NAME") == "iphoneos") def ios_app? end (framework? && build_settings(key: "PLATFORM_NAME") == "iphoneos") def ios_framework? end (ios? || tvos?) def ios_tvos_app? end ((static_library? or dynamic_library?) && build_settings(key: "PLATFORM_NAME") == "iphoneos") def ios_library? end (build_settings(key: "PRODUCT_TYPE") == "com.apple.product-type.application") def application? end (build_settings(key: "PRODUCT_TYPE") == "com.apple.product-type.framework") def framework? end (static_library? || dynamic_library?) def library? end (build_settings(key: "PRODUCT_TYPE") == "com.apple.product-type.library.static") def static_library? end (build_settings(key: "PRODUCT_TYPE") == "com.apple.product-type.library.dynamic") def dynamic_library? end return "App" # default value return name.gsub(build_settings(key: "WRAPPER_SUFFIX"), "") if name name = build_settings(key: "WRAPPER_NAME") # WRAPPER_SUFFIX: .app # WRAPPER_NAME: Example.app def app_name end end return app_name else return default_build_settings(key: "PRODUCT_NAME") if is_workspace def default_app_name # Returns app name and sets the scheme for xcrun end default_build_settings(key: "PRODUCT_BUNDLE_IDENTIFIER") def default_app_identifieradrOE|' x j b a 4  ~ a I ) o a 4 ( ' B k G 3%K]QGF:n[zrq {srX.e]\Brq # the first run times out after specified timeout elapses, and each successive run times out after # runs the specified command with the specified number of retries, killing each run if it times out. # @internal to module end (ENV['FASTLANE_XCODEBUILD_SETTINGS_RETRIES'] || 3).to_i def self.xcode_build_settings_retries # @internal to module end (ENV['FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT'] || 3).to_i def self.xcode_build_settings_timeout # @internal to module end build_settings(key: key, optional: optional) options[:scheme] ||= schemes.first if is_workspace def default_build_settings(key: nil, optional: true) # Returns the build settings and sets the default scheme to the options hash end nil end UI.error("Could not fetch #{key} from project file: #{ex}") UI.error(caller.join("\n\t")) return nil if optional # an optional value, we really don't care if something goes wrong rescue => ex return result.split(" = ").last end sp.first.strip == key next if sp.length == 0 sp = c.split(" = ") result = @build_settings.split("\n").find do |c| begin end end " and the number of retries with the environment variable FASTLANE_XCODEBUILD_SETTINGS_RETRIES ".red " You can override the base timeout value with the environment variable FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT," \ raise FastlaneCore::Interface::FastlaneDependencyCausedException.new, "xcodebuild -showBuildSettings timed out after #{retries + 1} retries with a base timeout of #{timeout}." \ rescue Timeout::Error end UI.error("Could not read build settings. Make sure that the scheme \"#{options[:scheme]}\" is configured for running by going to Product → Scheme → Edit Scheme…, selecting the \"Build\" section, checking the \"Run\" checkbox and closing the scheme window.") if @build_settings.empty? @build_settings = FastlaneCore::Project.run_command(command, timeout: timeout, retries: retries, print: !self.xcodebuild_list_silent) retries = FastlaneCore::Project.xcode_build_settings_retries timeout = FastlaneCore::Project.xcode_build_settings_timeout begin # Xcode might hang here and retrying fixes the problem, see fastlane#4059 command = build_xcodebuild_showbuildsettings_command end options[:scheme] ||= schemes.first end UI.user_error!("Could not find any schemes for Xcode workspace at path '#{self.path}'. Please make sure that the schemes you want to use are marked as `Shared` from Xcode.") if schemes.count == 0 if is_workspace unless @build_settings def build_settings(key: nil, optional: true) # @param [String] The key of which we want the value for (e.g. "PRODUCT_NAME") # e.g. to properly get the DerivedData folder # Get the build settings for our project end command command += " 2> /dev/null" if xcodebuild_suppress_stderr end command = "xcodebuild clean -showBuildSettings #{xcodebuild_parameters.join(' ')}" else command = "xcodebuild -showBuildSettings #{xcodebuild_parameters.join(' ')}" if FastlaneCore::Helper.xcode_at_least?('8.3') # See: https://github.com/fastlane/fastlane/pull/5626 # This xcodebuild bug is fixed in Xcode 8.3 so 'clean' it's not necessary anymore # The 'clean' portion of this command was a workaround for an xcodebuild bug with Core Data projects. # # We also need to pass the workspace and scheme to this command.adBvvQ return nil if workspace? de return nil if workspace? def project # returns the Xcodeproj::Project or nil if it is a workspace end @workspaceadN #@workspace.load_schemes(path) puts "??????????????????????? #@workspace.load_schemes(path) @workspace ||= Xcodeproj::Workspace.new_from_xcworkspace(path)ad0TT puts "!!!!!!! loading from path: #{path}" # https://github.com/CocoaPods/Xcodeproj/blob/80a2cdabd49eaaeff177a132c97b393f7337fbc9/lib/xcodeproj/workspace.rb#L85