Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Specify installation options via the podfile
  • Loading branch information
segiddins committed Dec 30, 2015
1 parent 6f6cd26 commit eb59c77
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 84 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Expand Up @@ -7,7 +7,7 @@ GIT

GIT
remote: https://github.com/CocoaPods/Core.git
revision: 3114804fac0ab28cd17ceb7d6fc29d0ca9c88e6e
revision: 93db7951de84e96562f5b47882f6307983155bf8
branch: seg-podfile-refactor
specs:
cocoapods-core (0.39.0)
Expand Down
4 changes: 0 additions & 4 deletions lib/cocoapods/command/project.rb
Expand Up @@ -39,8 +39,6 @@ module Project
module Options
def options
[
['--no-clean', 'Leave SCM dirs like `.git` and `.svn` intact after downloading'],
['--no-integrate', 'Skip integration of the Pods libraries in the Xcode project(s)'],
['--no-repo-update', 'Skip running `pod repo update` before install'],
].concat(super)
end
Expand All @@ -51,8 +49,6 @@ def self.included(base)
end

def initialize(argv)
config.clean = argv.flag?('clean', config.clean)
config.integrate_targets = argv.flag?('integrate', config.integrate_targets)
config.skip_repo_update = !argv.flag?('repo-update', !config.skip_repo_update)
super
end
Expand Down
33 changes: 0 additions & 33 deletions lib/cocoapods/config.rb
Expand Up @@ -17,11 +17,6 @@ class Config
:skip_repo_update => false,
:skip_download_cache => !ENV['COCOAPODS_SKIP_CACHE'].nil?,

:clean => true,
:integrate_targets => true,
:deduplicate_targets => true,
:deterministic_uuids => ENV['COCOAPODS_DISABLE_DETERMINISTIC_UUIDS'].nil?,
:lock_pod_source => true,
:new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?,

:cache_root => Pathname.new(Dir.home) + 'Library/Caches/CocoaPods',
Expand Down Expand Up @@ -74,34 +69,6 @@ def with_changes(changes)

# @!group Installation

# @return [Bool] Whether the installer should clean after the installation.
#
attr_accessor :clean
alias_method :clean?, :clean

# @return [Bool] Whether the installer should remove write permissions for
# installed pod source files after the installation.
#
attr_accessor :lock_pod_source
alias_method :lock_pod_source?, :lock_pod_source

# @return [Bool] Whether CocoaPods should integrate a user target and build
# the workspace or just create the Pods project.
#
attr_accessor :integrate_targets
alias_method :integrate_targets?, :integrate_targets

# @return [Bool] Whether CocoaPods should deduplicate pod targets.
#
attr_accessor :deduplicate_targets
alias_method :deduplicate_targets?, :deduplicate_targets

# @return [Bool] Whether CocoaPods should give the pods project
# deterministic UUIDs.
#
attr_accessor :deterministic_uuids
alias_method :deterministic_uuids?, :deterministic_uuids

# @return [Bool] Whether the installer should skip the repos update.
#
attr_accessor :skip_repo_update
Expand Down
3 changes: 2 additions & 1 deletion lib/cocoapods/downloader.rb
Expand Up @@ -27,7 +27,8 @@ module Downloader
def self.download(
request,
target,
cache_path: !Config.instance.skip_download_cache && Config.instance.clean? && Config.instance.cache_root + 'Pods'
can_cache: true,
cache_path: can_cache && !Config.instance.skip_download_cache && Config.instance.cache_root + 'Pods'
)
if cache_path
cache = Cache.new(cache_path)
Expand Down
6 changes: 5 additions & 1 deletion lib/cocoapods/external_sources/abstract_external_source.rb
Expand Up @@ -17,6 +17,9 @@ class AbstractExternalSource
#
attr_reader :podfile_path

attr_accessor :can_cache
alias_method :can_cache?, :can_cache

# Initialize a new instance
#
# @param [String] name @see name
Expand All @@ -27,6 +30,7 @@ def initialize(name, params, podfile_path)
@name = name
@params = params
@podfile_path = podfile_path
@can_cache = true
end

# @return [Bool] whether an external source source is equal to another
Expand Down Expand Up @@ -105,7 +109,7 @@ def pre_download(sandbox)
title = "Pre-downloading: `#{name}` #{description}"
UI.titled_section(title, :verbose_prefix => '-> ') do
target = sandbox.pod_dir(name)
download_result = Downloader.download(download_request, target)
download_result = Downloader.download(download_request, target, :can_cache => can_cache)
spec = download_result.spec

raise Informative, "Unable to find a specification for '#{name}'." unless spec
Expand Down
18 changes: 12 additions & 6 deletions lib/cocoapods/installer.rb
Expand Up @@ -32,6 +32,7 @@ class Installer
autoload :AggregateTargetInstaller, 'cocoapods/installer/target_installer/aggregate_target_installer'
autoload :Analyzer, 'cocoapods/installer/analyzer'
autoload :FileReferencesInstaller, 'cocoapods/installer/file_references_installer'
autoload :InstallationOptions, 'cocoapods/installer/installation_options'
autoload :PostInstallHooksContext, 'cocoapods/installer/post_install_hooks_context'
autoload :PreInstallHooksContext, 'cocoapods/installer/pre_install_hooks_context'
autoload :SourceProviderHooksContext, 'cocoapods/installer/source_provider_hooks_context'
Expand All @@ -44,6 +45,9 @@ class Installer
autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'

include Config::Mixin
include InstallationOptions::Mixin

delegate_installation_options { podfile }

# @return [Sandbox] The sandbox where the Pods should be installed.
#
Expand Down Expand Up @@ -109,7 +113,7 @@ def install!
verify_no_static_framework_transitive_dependencies
verify_framework_usage
generate_pods_project
integrate_user_project if config.integrate_targets?
integrate_user_project if integrate_targets?
perform_post_install_actions
end

Expand Down Expand Up @@ -221,7 +225,9 @@ def analyze(analyzer = create_analyzer)
end

def create_analyzer
Analyzer.new(sandbox, podfile, lockfile)
Analyzer.new(sandbox, podfile, lockfile).tap do |analyzer|
analyzer.installation_options = installation_options
end
end

# Ensures that the white-listed build configurations are known to prevent
Expand Down Expand Up @@ -318,7 +324,7 @@ def create_pod_installer(pod_name)
end

@pod_installers ||= []
pod_installer = PodSourceInstaller.new(sandbox, specs_by_platform)
pod_installer = PodSourceInstaller.new(sandbox, specs_by_platform, can_cache: clean?)
@pod_installers << pod_installer
pod_installer
end
Expand All @@ -340,7 +346,7 @@ def install_source_of_pod(pod_name)
# @todo Why the @pod_installers might be empty?
#
def clean_pod_sources
return unless config.clean?
return unless clean?
return unless @pod_installers
@pod_installers.each(&:clean!)
end
Expand All @@ -362,7 +368,7 @@ def unlock_pod_sources
# @todo Why the @pod_installers might be empty?
#
def lock_pod_sources
return unless config.lock_pod_source?
return unless lock_pod_sources?
return unless @pod_installers
@pod_installers.each do |installer|
pod_target = pod_targets.find { |target| target.pod_name == installer.name }
Expand Down Expand Up @@ -706,7 +712,7 @@ def write_pod_project
pods_project.development_pods.remove_from_project if pods_project.development_pods.empty?
pods_project.sort(:groups_position => :below)
pods_project.recreate_user_schemes(false)
if config.deterministic_uuids?
if deterministic_uuids?
UI.message('- Generating deterministic UUIDs') { pods_project.predictabilize_uuids }
end
pods_project.save
Expand Down
14 changes: 9 additions & 5 deletions lib/cocoapods/installer/analyzer.rb
Expand Up @@ -5,6 +5,9 @@ class Installer
#
class Analyzer
include Config::Mixin
include InstallationOptions::Mixin

delegate_installation_options { podfile }

autoload :AnalysisResult, 'cocoapods/installer/analyzer/analysis_result'
autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer'
Expand Down Expand Up @@ -57,7 +60,7 @@ def analyze(allow_fetches = true)
validate_podfile!
validate_lockfile_version!
@result = AnalysisResult.new
if config.integrate_targets?
if integrate_targets?
@result.target_inspections = inspect_targets_to_integrate
else
verify_platforms_specified!
Expand Down Expand Up @@ -249,7 +252,7 @@ def generate_target(target_definition, pod_targets)
target = AggregateTarget.new(target_definition, sandbox)
target.host_requires_frameworks |= target_definition.uses_frameworks?

if config.integrate_targets?
if integrate_targets?
target_inspection = result.target_inspections[target_definition]
raise "missing inspection: #{target_definition.name}" unless target_inspection
target.user_project = target_inspection.project
Expand Down Expand Up @@ -282,7 +285,7 @@ def generate_target(target_definition, pod_targets)
# @return [Array<PodTarget>]
#
def generate_pod_targets(specs_by_target)
if config.deduplicate_targets?
if deduplicate_targets?
dedupe_cache = {}

all_specs = specs_by_target.flat_map do |target_definition, dependent_specs|
Expand Down Expand Up @@ -377,7 +380,7 @@ def transitive_dependencies_for_pod_target(pod_target, targets)
def generate_pod_target(target_definitions, pod_specs)
pod_target = PodTarget.new(pod_specs, target_definitions, sandbox)

if config.integrate_targets?
if integrate_targets?
target_inspections = result.target_inspections.select { |t, _| target_definitions.include?(t) }.values
pod_target.user_build_configurations = target_inspections.map(&:build_configurations).reduce({}, &:merge)
pod_target.archs = target_inspections.flat_map(&:archs).compact.uniq.sort
Expand Down Expand Up @@ -462,6 +465,7 @@ def fetch_external_source(dependency, use_lockfile_options)
else
source = ExternalSources.from_dependency(dependency, podfile.defined_in_file)
end
source.can_cache = clean?
source.fetch(sandbox)
end

Expand Down Expand Up @@ -650,7 +654,7 @@ def sources
# @return [void]
#
def verify_platforms_specified!
unless config.integrate_targets?
unless integrate_targets?
podfile.target_definition_list.each do |target_definition|
if !target_definition.empty? && target_definition.platform.nil?
raise Informative, 'It is necessary to specify the platform in the Podfile if not integrating.'
Expand Down
71 changes: 71 additions & 0 deletions lib/cocoapods/installer/installation_options.rb
@@ -0,0 +1,71 @@
require 'active_support/hash_with_indifferent_access'

module Pod
class Installer
class InstallationOptions
def self.from_podfile(podfile)
name = podfile.installation_method['name']
unless name.downcase == 'cocoapods'
raise Informative "currently need to specify a cocoapods install, you chose #{name}"
end
options = podfile.installation_method['options']
new(options)
end

def self.option(name, default, boolean: true)
name = name.to_s
raise 'existing' if defaults.key?(name)
defaults[name] = default
attr_accessor name
alias_method "#{name}?", name if boolean
end

def self.defaults
@defaults ||= {}
end

def self.all_options
defaults.keys
end

def initialize(options)
options = ActiveSupport::HashWithIndifferentAccess.new(options)
unknown_keys = options.keys - self.class.all_options.map(&:to_s)
raise Informative, "Unknown installation options: #{unknown_keys.to_sentence}" unless unknown_keys.empty?
self.class.defaults.each do |key, default|
value = options.fetch(key, default)
send("#{key}=", value)
end
end

option :clean, true
option :deduplicate_targets, true
option :deterministic_uuids, true
option :integrate_targets, true
option :lock_pod_sources, true

module Mixin
def Mixin.included(mod)
mod.send(:attr_accessor, :installation_options)
def mod.delegate_installation_options(&blk)
define_method(:installation_options) do
@installation_options ||= InstallationOptions.from_podfile(instance_eval(&blk))
end
end
end

def respond_to_missing?(name, *args)
installation_options.respond_to?(name, *args) || super
end

def method_missing(name, *args, &blk)
if installation_options.respond_to?(name)
installation_options.send(name, *args, &blk)
else
super
end
end
end
end
end
end
11 changes: 9 additions & 2 deletions lib/cocoapods/installer/pod_source_installer.rb
Expand Up @@ -17,14 +17,21 @@ class PodSourceInstaller
#
attr_reader :specs_by_platform

# @return [Boolean] Whether the installer is allowed to touch the cache.
#
attr_reader :can_cache
alias_method :can_cache?, :can_cache

# Initialize a new instance
#
# @param [Sandbox] sandbox @see sandbox
# @param [Hash{Symbol=>Array}] specs_by_platform @see specs_by_platform
# @param [Boolean] can_cache @see can_cache
#
def initialize(sandbox, specs_by_platform)
def initialize(sandbox, specs_by_platform, can_cache: true)
@sandbox = sandbox
@specs_by_platform = specs_by_platform
@can_cache = can_cache
end

# @return [String] A string suitable for debugging.
Expand Down Expand Up @@ -110,7 +117,7 @@ def unlock_files!(file_accessors)
# @return [void]
#
def download_source
download_result = Downloader.download(download_request, root)
download_result = Downloader.download(download_request, root, :can_cache => can_cache?)

if (@specific_source = download_result.checkout_options) && specific_source != root_spec.source
sandbox.store_checkout_source(root_spec.name, specific_source)
Expand Down
3 changes: 1 addition & 2 deletions lib/cocoapods/validator.rb
Expand Up @@ -354,9 +354,7 @@ def setup_validation_environment
@original_config = Config.instance.clone
config.installation_root = validation_dir
config.silent = !config.verbose
config.integrate_targets = true
config.skip_repo_update = true
config.deterministic_uuids = false
end

def tear_down_validation_environment
Expand Down Expand Up @@ -664,6 +662,7 @@ def podfile_from_spec(platform_name, deployment_target, use_frameworks = true)
local = local?
urls = source_urls
Pod::Podfile.new do
install! 'cocoapods', :deterministic_uuids => false
urls.each { |u| source(u) }
target 'App' do
use_frameworks!(use_frameworks)
Expand Down
16 changes: 0 additions & 16 deletions spec/unit/config_spec.rb
Expand Up @@ -176,22 +176,6 @@ module Pod
@config.should.not.be.verbose
end

it 'cleans SCM dirs in dependency checkouts' do
@config.should.clean
end

it 'locks pod source files' do
@config.should.lock_pod_source
end

it 'integrates a user target' do
@config.should.integrate_targets
end

it 'de-duplicates targets' do
@config.should.deduplicate_targets
end

it 'returns the cache root' do
@config.cache_root.should == Pathname.new(File.join(ENV['HOME'], 'Library/Caches/CocoaPods'))
end
Expand Down

0 comments on commit eb59c77

Please sign in to comment.