module Lhj # Stores the global configuration of CocoaPods. # class Config # The default settings for the configuration. # # Users can specify custom settings in `~/.cocoapods/config.yaml`. # An example of the contents of this file might look like: # # --- # skip_repo_update: true # new_version_message: false # DEFAULTS = { :verbose => false, :silent => false, :skip_download_cache => !ENV['COCOAPODS_SKIP_CACHE'].nil?, :new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?, :cache_root => Pathname.new(Dir.home) + 'Library/Caches/CocoaPods', } # Applies the given changes to the config for the duration of the given # block. # # @param [Hash<#to_sym,Object>] changes # the changes to merge temporarily with the current config # # @yield [] is called while the changes are applied # def with_changes(changes) old = {} changes.keys.each do |key| key = key.to_sym old[key] = send(key) if respond_to?(key) end configure_with(changes) yield if block_given? ensure configure_with(old) end public #-------------------------------------------------------------------------# # @!group UI # @return [Boolean] Whether CocoaPods should provide detailed output about the # performed actions. # attr_accessor :verbose alias_method :verbose?, :verbose # @return [Boolean] Whether CocoaPods should produce not output. # attr_accessor :silent alias_method :silent?, :silent # @return [Boolean] Whether CocoaPods is allowed to run as root. # attr_accessor :allow_root alias_method :allow_root?, :allow_root # @return [Boolean] Whether a message should be printed when a new version of # CocoaPods is available. # attr_accessor :new_version_message alias_method :new_version_message?, :new_version_message #-------------------------------------------------------------------------# # @!group Installation # @return [Boolean] Whether the installer should skip the download cache. # attr_accessor :skip_download_cache alias_method :skip_download_cache?, :skip_download_cache public #-------------------------------------------------------------------------# # @!group Cache # @return [Pathname] The directory where CocoaPods should cache remote data # and other expensive to compute information. # attr_accessor :cache_root def cache_root @cache_root.mkpath unless @cache_root.exist? @cache_root end public #-------------------------------------------------------------------------# # @!group Initialization def initialize(use_user_settings = true) configure_with(DEFAULTS) unless ENV['CP_HOME_DIR'].nil? @cache_root = home_dir + 'cache' end if use_user_settings && user_settings_file.exist? require 'yaml' user_settings = YAML.load_file(user_settings_file) configure_with(user_settings) end unless ENV['CP_CACHE_DIR'].nil? @cache_root = Pathname.new(ENV['CP_CACHE_DIR']).expand_path end end def verbose @verbose && !silent end public #-------------------------------------------------------------------------# # @!group Paths # @return [Pathname] the directory where repos, templates and configuration # files are stored. # def home_dir @home_dir ||= Pathname.new(ENV['CP_HOME_DIR'] || '~/.lhj').expand_path end # @return [Pathname] the directory where the CocoaPods sources are stored. # def repos_dir @repos_dir ||= Pathname.new(ENV['CP_REPOS_DIR'] || (home_dir + 'repos')).expand_path end attr_writer :repos_dir # @return [Source::Manager] the source manager for the spec repos in `repos_dir` # def sources_manager return @sources_manager if @sources_manager && @sources_manager.repos_dir == repos_dir @sources_manager = Source::Manager.new(repos_dir) end # @return [Pathname] the directory where the CocoaPods templates are stored. # def templates_dir @templates_dir ||= Pathname.new(ENV['CP_TEMPLATES_DIR'] || (home_dir + 'templates')).expand_path end # @return [Pathname] the root of the CocoaPods installation where the # Podfile is located. # def installation_root @installation_root ||= begin current_dir = Pathname.new(Dir.pwd.unicode_normalize(:nfkc)) current_path = current_dir until current_path.root? if podfile_path_in_dir(current_path) installation_root = current_path unless current_path == current_dir UI.puts("[in #{current_path}]") end break else current_path = current_path.parent end end installation_root || current_dir end end attr_writer :installation_root alias_method :project_root, :installation_root # @return [Pathname] The root of the sandbox. # def sandbox_root @sandbox_root ||= installation_root + 'Pods' end attr_writer :sandbox_root alias_method :project_pods_root, :sandbox_root # @return [Sandbox] The sandbox of the current project. # def sandbox @sandbox ||= Sandbox.new(sandbox_root) end # @return [Podfile] The Podfile to use for the current execution. # @return [Nil] If no Podfile is available. # def podfile @podfile ||= Podfile.from_file(podfile_path) if podfile_path end attr_writer :podfile # @return [Lockfile] The Lockfile to use for the current execution. # @return [Nil] If no Lockfile is available. # def lockfile @lockfile ||= Lockfile.from_file(lockfile_path) if lockfile_path end # Returns the path of the Podfile. # # @note The Podfile can be named either `CocoaPods.podfile.yaml`, # `CocoaPods.podfile` or `Podfile`. The first two are preferred as # they allow to specify an OS X UTI. # # @return [Pathname] # @return [Nil] # def podfile_path @podfile_path ||= podfile_path_in_dir(installation_root) end # Returns the path of the Lockfile. # # @note The Lockfile is named `Podfile.lock`. # def lockfile_path @lockfile_path ||= installation_root + 'Podfile.lock' end # Returns the path of the default Podfile pods. # # @note The file is expected to be named Podfile.default # # @return [Pathname] # def default_podfile_path @default_podfile_path ||= templates_dir + 'Podfile.default' end # Returns the path of the default Podfile test pods. # # @note The file is expected to be named Podfile.test # # @return [Pathname] # def default_test_podfile_path @default_test_podfile_path ||= templates_dir + 'Podfile.test' end # @return [Pathname] The file to use to cache the search data. # def search_index_file cache_root + 'search_index.json' end private #-------------------------------------------------------------------------# # @!group Private helpers # @return [Pathname] The path of the file which contains the user settings. # def user_settings_file home_dir + 'config.yaml' end # Sets the values of the attributes with the given hash. # # @param [Hash{String,Symbol => Object}] values_by_key # The values of the attributes grouped by key. # # @return [void] # def configure_with(values_by_key) return unless values_by_key values_by_key.each do |key, value| if key.to_sym == :cache_root value = Pathname.new(value).expand_path end instance_variable_set("@#{key}", value) end end # @return [Array] The filenames that the Podfile can have ordered # by priority. # PODFILE_NAMES = [ 'CocoaPods.podfile.yaml', 'CocoaPods.podfile', 'Podfile', 'Podfile.rb', ].freeze public # Returns the path of the Podfile in the given dir if any exists. # # @param [Pathname] dir # The directory where to look for the Podfile. # # @return [Pathname] The path of the Podfile. # @return [Nil] If not Podfile was found in the given dir # def podfile_path_in_dir(dir) PODFILE_NAMES.each do |filename| candidate = dir + filename if candidate.file? return candidate end end nil end # Excludes the given dir from Time Machine backups. # # @param [Pathname] dir # The directory to exclude from Time Machine backups. # # @return [void] # def exclude_from_backup(dir) return if Gem.win_platform? system('tmutil', 'addexclusion', dir.to_s, %i(out err) => File::NULL) end public #-------------------------------------------------------------------------# # @!group Singleton # @return [Config] the current config instance creating one if needed. # def self.instance @instance ||= new end # Sets the current config instance. If set to nil the config will be # recreated when needed. # # @param [Config, Nil] the instance. # # @return [void] # class << self attr_writer :instance end # Provides support for accessing the configuration instance in other # scopes. # module Mixin def config Config.instance end end end end