Commit b611ae93 authored by Samuel E. Giddins's avatar Samuel E. Giddins

Merge pull request #4644 from CocoaPods/seg-podfile-refactor

Podfile Refactor
parents 71ce9d47 78314087
......@@ -6,6 +6,40 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
## Master
##### Breaking
* The `link_with` Podfile DSL method has been removed in favor of target
inheritance.
[Samuel Giddins](https://github.com/segiddins)
* The `:exclusive => true` Podfile DSL target option has been removed in favor
of the `inherit! :search_paths` directive.
[Samuel Giddins](https://github.com/segiddins)
* The specification of `:head` dependencies has been removed.
[Samuel Giddins](https://github.com/segiddins)
[#4673](https://github.com/CocoaPods/CocoaPods/issues/4673)
* The deprecated `:local` dependency option has been removed in favor of the
equivalent `:path` option.
[Samuel Giddins](https://github.com/segiddins)
* The deprecated `dependency` method in the Podfile DSL has been removed in
favor of the equivalent `pod` method.
[Samuel Giddins](https://github.com/segiddins)
* The deprecated `preferred_dependency` method in the Specification DSL has been
removed in favor of the equivalent `default_subspecs` method.
[Samuel Giddins](https://github.com/segiddins)
##### Highlighted Enhancements That Need Testing
* The Podfile DSL has been cleaned up, with the removal of confusing options and
the introduction of abstract targets, search paths-only inheritance, the
specification of installation options, and the removal of head dependencies.
[Samuel Giddins](https://github.com/segiddins)
[#840](https://github.com/CocoaPods/CocoaPods/issues/840)
##### Enhancements
* Add the ability to add a custom commit message when pushing a spec.
......@@ -101,6 +135,18 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
changes, ensuring backwards-incompatible changes are properly applied.
[Samuel Giddins](https://github.com/segiddins)
* The Podfile now allows specifying installation options via the `install!`
directive.
[Samuel Giddins](https://github.com/segiddins)
[Core#151](https://github.com/CocoaPods/Core/issues/151)
* The Podfile now allows marking targets as `abstract` and specifying the pod
inheritance mode via the `inherit!` directive.
[Samuel Giddins](https://github.com/segiddins)
[#1249](https://github.com/CocoaPods/CocoaPods/issues/1249)
[#1626](https://github.com/CocoaPods/CocoaPods/issues/1626)
[#4001](https://github.com/CocoaPods/CocoaPods/issues/4001)
##### Bug Fixes
* Fix compiling of localized resources.
......@@ -184,6 +230,10 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
[Samuel Giddins](https://github.com/segiddins)
[#4550](https://github.com/CocoaPods/CocoaPods/issues/4550)
* Empty podfiles / target blocks no longer break the user's Xcode project.
[Samuel Giddins](https://github.com/segiddins)
[#3617](https://github.com/CocoaPods/CocoaPods/issues/3617)
## 0.39.0 (2015-10-09)
......
......@@ -7,7 +7,7 @@ GIT
GIT
remote: https://github.com/CocoaPods/Core.git
revision: 0851a1e712e1e1c206ed03f67a25ef28af52fa69
revision: ca0a5d504357e48da31b274430a966d64fd62078
branch: master
specs:
cocoapods-core (0.39.0)
......
......@@ -39,8 +39,6 @@ module Pod
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
......@@ -51,8 +49,6 @@ module Pod
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
......
......@@ -34,8 +34,6 @@ module Pod
set_master_repo_url
set_master_repo_branch
update_master_repo
elsif old_master_repo_dir.exist?
migrate_repos
else
add_master_repo
end
......@@ -48,22 +46,6 @@ module Pod
# @!group Setup steps
# Migrates any repos from the old directory structure to the new
# directory structure.
#
# @todo: Remove by 1.0
#
def migrate_repos
config.repos_dir.mkpath
Dir.foreach old_master_repo_dir.parent do |repo_dir|
source_repo_dir = old_master_repo_dir.parent + repo_dir
target_repo_dir = config.repos_dir + repo_dir
if repo_dir !~ /\.+/ && source_repo_dir != config.repos_dir
FileUtils.mv source_repo_dir, target_repo_dir
end
end
end
# Sets the url of the master repo according to whether it is push.
#
# @return [void]
......@@ -127,12 +109,6 @@ module Pod
def master_repo_dir
SourcesManager.master_repo_dir
end
# @return [Pathname] the directory of the old master repo.
#
def old_master_repo_dir
Pathname.new('~/.cocoapods/master').expand_path
end
end
end
end
......@@ -17,11 +17,6 @@ module Pod
: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',
......@@ -74,34 +69,6 @@ module Pod
# @!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
......
......@@ -20,16 +20,21 @@ module Pod
# the location to which this pod should be downloaded. If `nil`,
# then the pod will only be cached.
#
# @param [Boolean] can_cache
# whether caching is allowed.
#
# @param [Pathname,Nil] cache_path
# the path used to cache pod downloads. If `nil`, then no caching
# will be done.
# the path used to cache pod downloads.
#
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: Config.instance.cache_root + 'Pods'
)
if cache_path
can_cache &&= !Config.instance.skip_download_cache
if can_cache
raise ArgumentError, 'Must provide a `cache_path` when caching.' unless cache_path
cache = Cache.new(cache_path)
result = cache.download_pod(request)
else
......
......@@ -46,10 +46,6 @@ module Pod
PodspecSource
elsif params.key?(:path)
PathSource
elsif params.key?(:local)
UI.warn 'The `:local` option of the Podfile has been ' \
'renamed to `:path` and it is deprecated.'
PathSource
elsif Downloader.strategy_from_options(params)
DownloaderSource
end
......
......@@ -17,6 +17,11 @@ module Pod
#
attr_reader :podfile_path
# @return [Boolean] Whether the source is allowed to touch the cache.
#
attr_accessor :can_cache
alias_method :can_cache?, :can_cache
# Initialize a new instance
#
# @param [String] name @see name
......@@ -27,6 +32,7 @@ module Pod
@name = name
@params = params
@podfile_path = podfile_path
@can_cache = true
end
# @return [Bool] whether an external source source is equal to another
......@@ -105,7 +111,7 @@ module Pod
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
......
......@@ -24,7 +24,7 @@ module Pod
# @see AbstractExternalSource#description
#
def description
"from `#{params[:path] || params[:local]}`"
"from `#{declared_path}`"
end
private
......@@ -34,7 +34,7 @@ module Pod
# @return [String] The path as declared by the user.
#
def declared_path
result = params[:path] || params[:local]
result = params[:path]
result.to_s if result
end
......
......@@ -87,15 +87,12 @@ module Pod
#---------------------------------------------------------------------#
private
protected
# Add build settings, which ensure that the pod targets can be imported
# from the integrating target by all sort of imports, which are:
# - `#import <…>`
# - `#import "…"`
# - `@import …;` / `import …`
# @return [Hash<String, String>] the build settings necessary to import
# the pod targets.
#
def generate_settings_to_import_pod_targets
def settings_to_import_pod_targets
if target.requires_frameworks?
framework_header_search_paths = pod_targets.select(&:should_build?).map do |target|
if target.scoped?
......@@ -118,17 +115,32 @@ module Pod
if pod_targets.any? { |t| t.should_build? && t.scoped? }
build_settings['FRAMEWORK_SEARCH_PATHS'] = '"$PODS_FRAMEWORK_BUILD_PATH"'
end
@xcconfig.merge!(build_settings)
build_settings
else
# Make headers discoverable from $PODS_ROOT/Headers directory
header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
build_settings = {
{
# by `#import "…"`
'HEADER_SEARCH_PATHS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths),
# by `#import <…>`
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-isystem'),
}
@xcconfig.merge!(build_settings)
end
end
private
# Add build settings, which ensure that the pod targets can be imported
# from the integrating target by all sort of imports, which are:
# - `#import <…>`
# - `#import "…"`
# - `@import …;` / `import …`
#
def generate_settings_to_import_pod_targets
@xcconfig.merge!(settings_to_import_pod_targets)
target.search_paths_aggregate_targets.each do |search_paths_target|
generator = AggregateXCConfig.new(search_paths_target, configuration_name)
@xcconfig.merge!(generator.settings_to_import_pod_targets)
end
end
......
......@@ -44,11 +44,9 @@ module Pod
#
def initialize(name, plugin_name, block)
raise ArgumentError, 'Missing name' unless name
raise ArgumentError, 'Missing plugin_name' unless plugin_name
raise ArgumentError, 'Missing block' unless block
UI.warn '[Hooks] The use of hooks without specifying a `plugin_name` ' \
"has been deprecated (from file `#{block.binding.eval('File.expand_path __FILE__')}`)." unless plugin_name
@name = name
@plugin_name = plugin_name
@block = block
......@@ -72,13 +70,7 @@ module Pod
# @param [Proc] block
# The block.
#
def register(plugin_name, hook_name = nil, &block)
# TODO: Backwards compatibility with nameless plugins from CP 0.34
if hook_name.nil?
hook_name = plugin_name
plugin_name = nil
end
def register(plugin_name, hook_name, &block)
@registrations ||= {}
@registrations[hook_name] ||= []
@registrations[hook_name] << Hook.new(hook_name, plugin_name, block)
......@@ -108,7 +100,7 @@ module Pod
UI.message "- Running #{name.to_s.tr('_', ' ')} hooks" do
hooks.each do |hook|
next if whitelisted_plugins && !whitelisted_plugins.key?(hook.plugin_name)
UI.message "- #{hook.plugin_name || 'unknown plugin'} from " \
UI.message "- #{hook.plugin_name} from " \
"`#{hook.block.source_location.first}`" do
block = hook.block
if block.arity > 1
......
......@@ -32,6 +32,7 @@ module Pod
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'
......@@ -44,6 +45,9 @@ module Pod
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.
#
......@@ -109,7 +113,7 @@ module Pod
verify_no_static_framework_transitive_dependencies
verify_framework_usage
generate_pods_project
integrate_user_project if config.integrate_targets?
integrate_user_project if installation_options.integrate_targets?
perform_post_install_actions
end
......@@ -221,7 +225,9 @@ module Pod
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
......@@ -318,7 +324,7 @@ module Pod
end
@pod_installers ||= []
pod_installer = PodSourceInstaller.new(sandbox, specs_by_platform)
pod_installer = PodSourceInstaller.new(sandbox, specs_by_platform, :can_cache => installation_options.clean?)
@pod_installers << pod_installer
pod_installer
end
......@@ -340,7 +346,7 @@ module Pod
# @todo Why the @pod_installers might be empty?
#
def clean_pod_sources
return unless config.clean?
return unless installation_options.clean?
return unless @pod_installers
@pod_installers.each(&:clean!)
end
......@@ -362,7 +368,7 @@ module Pod
# @todo Why the @pod_installers might be empty?
#
def lock_pod_sources
return unless config.lock_pod_source?
return unless installation_options.lock_pod_sources?
return unless @pod_installers
@pod_installers.each do |installer|
pod_target = pod_targets.find { |target| target.pod_name == installer.name }
......@@ -623,13 +629,13 @@ module Pod
def install_libraries
UI.message '- Installing targets' do
pod_targets.sort_by(&:name).each do |pod_target|
next if pod_target.target_definitions.flat_map(&:dependencies).empty?
next if pod_target.target_definitions.all?(&:abstract?)
target_installer = PodTargetInstaller.new(sandbox, pod_target)
target_installer.install!
end
aggregate_targets.sort_by(&:name).each do |target|
next if target.target_definition.dependencies.empty?
next if target.target_definition.abstract?
target_installer = AggregateTargetInstaller.new(sandbox, target)
target_installer.install!
end
......@@ -706,7 +712,7 @@ module Pod
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 installation_options.deterministic_uuids?
UI.message('- Generating deterministic UUIDs') { pods_project.predictabilize_uuids }
end
pods_project.save
......
......@@ -5,6 +5,9 @@ module Pod
#
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'
......@@ -57,7 +60,7 @@ module Pod
validate_podfile!
validate_lockfile_version!
@result = AnalysisResult.new
if config.integrate_targets?
if installation_options.integrate_targets?
@result.target_inspections = inspect_targets_to_integrate
else
verify_platforms_specified!
......@@ -157,6 +160,7 @@ module Pod
unless validator.valid?
raise Informative, validator.message
end
validator.warnings.uniq.each { |w| UI.warn(w) }
end
# @!group Analysis steps
......@@ -225,9 +229,14 @@ module Pod
#
def generate_targets
pod_targets = generate_pod_targets(result.specs_by_target)
result.specs_by_target.map do |target_definition, _|
aggregate_targets = result.specs_by_target.keys.reject(&:abstract?).map do |target_definition|
generate_target(target_definition, pod_targets)
end
aggregate_targets.each do |target|
target.search_paths_aggregate_targets = aggregate_targets.select do |aggregate_target|
target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition)
end
end
end
# Setup the aggregate target for a single user target
......@@ -244,8 +253,9 @@ module Pod
target = AggregateTarget.new(target_definition, sandbox)
target.host_requires_frameworks |= target_definition.uses_frameworks?
if config.integrate_targets?
if installation_options.integrate_targets?
target_inspection = result.target_inspections[target_definition]
raise "missing inspection: #{target_definition.name}" unless target_inspection
target.user_project = target_inspection.project
target.client_root = target.user_project_path.dirname.realpath
target.user_target_uuids = target_inspection.project_target_uuids
......@@ -276,7 +286,7 @@ module Pod
# @return [Array<PodTarget>]
#
def generate_pod_targets(specs_by_target)
if config.deduplicate_targets?
if installation_options.deduplicate_targets?
dedupe_cache = {}
all_specs = specs_by_target.flat_map do |target_definition, dependent_specs|
......@@ -371,7 +381,7 @@ module Pod
def generate_pod_target(target_definitions, pod_specs)
pod_target = PodTarget.new(pod_specs, target_definitions, sandbox)
if config.integrate_targets?
if installation_options.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
......@@ -456,6 +466,7 @@ module Pod
else
source = ExternalSources.from_dependency(dependency, podfile.defined_in_file)
end
source.can_cache = installation_options.clean?
source.fetch(sandbox)
end
......@@ -471,7 +482,6 @@ module Pod
deps_to_fetch_if_needed = deps_with_external_source.select { |dep| result.podfile_state.unchanged.include?(dep.name) }
deps_to_fetch += deps_to_fetch_if_needed.select do |dep|
sandbox.specification(dep.name).nil? ||
!dep.external_source[:local].nil? ||
!dep.external_source[:path].nil? ||
!sandbox.pod_dir(dep.root_name).directory? ||
checkout_requires_update?(dep)
......@@ -644,7 +654,7 @@ module Pod
# @return [void]
#
def verify_platforms_specified!
unless config.integrate_targets?
unless installation_options.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.'
......@@ -665,8 +675,9 @@ module Pod
inspection_result = {}
UI.section 'Inspecting targets to integrate' do
inspectors = podfile.target_definition_list.map do |target_definition|
next if target_definition.abstract?
TargetInspector.new(target_definition, config.installation_root)
end
end.compact
inspectors.group_by(&:compute_project_path).each do |project_path, target_inspectors|
project = Xcodeproj::Project.open(project_path)
target_inspectors.each do |inspector|
......
......@@ -14,7 +14,7 @@ module Pod
# - The version of the Pod changed.
# - The SHA of the specification file changed.
# - The specific installed (sub)specs of the same Pod changed.
# - The specification is in head mode or from an external source and the
# - The specification is from an external source and the
# installation process is in update mode.
# - The directory of the Pod is empty.
# - The Pod has been pre-downloaded.
......@@ -135,7 +135,7 @@ module Pod
# changed and thus should be reinstalled.
#
# @note In update mode, as there is no way to know if a remote source
# hash changed the Pods in head mode and the ones from external
# hash changed the Pods from external
# sources are always marked as changed.
#
# @note A Pod whose folder is empty is considered changed.
......@@ -152,10 +152,6 @@ module Pod
return true if resolved_spec_names(pod) != sandbox_spec_names(pod)
return true if sandbox.predownloaded?(pod)
return true if folder_empty?(pod)
return true if sandbox.head_pod?(pod) != sandbox_head_version?(pod)
if update_mode
return true if sandbox.head_pod?(pod)
end
false
end
......@@ -238,13 +234,6 @@ module Pod
sandbox_manifest.checksum(pod)
end
# @return [Bool] Wether the Pod is installed in the sandbox is in head
# mode.
#
def sandbox_head_version?(pod)
sandbox_version(pod).head? == true
end
#--------------------------------------#
def folder_exist?(pod)
......
require 'active_support/core_ext/array/conversions'
module Pod
class Installer
class Analyzer
......@@ -102,19 +104,12 @@ module Pod
#
def compute_targets(user_project)
native_targets = user_project.native_targets
if link_with = target_definition.link_with
targets = native_targets.select { |t| link_with.include?(t.name) }
raise Informative, "Unable to find the targets named #{link_with.map { |x| "`#{x}`" }.to_sentence}" \
"to link with target definition `#{target_definition.name}`" if targets.empty?
elsif target_definition.link_with_first_target?
targets = [native_targets.first].compact
raise Informative, 'Unable to find a target' if targets.empty?
else
target = native_targets.find { |t| t.name == target_definition.name.to_s }
targets = [target].compact
raise Informative, "Unable to find a target named `#{target_definition.name}`" if targets.empty?
unless target
found = native_targets.map { |t| "`#{t.name}`" }.to_sentence
raise Informative, "Unable to find a target named `#{target_definition.name}`, did find #{found}."
end
targets
[target]
end
# @param [Array<PBXNativeTarget] the user's targets of the project of
......
require 'active_support/hash_with_indifferent_access'
module Pod
class Installer
# Represents the installation options the user can customize via a
# `Podfile`.
#
class InstallationOptions
# Parses installation options from a podfile.
#
# @param [Podfile] podfile the podfile to parse installation options
# from.
#
# @raise [Informative] if `podfile` does not specify a `CocoaPods`
# install.
#
# @return [Self]
#
def self.from_podfile(podfile)
name, options = podfile.installation_method
unless name.downcase == 'cocoapods'
raise Informative, "Currently need to specify a `cocoapods` install, you chose `#{name}`."
end
new(options)
end
# Defines a new installation option.
#
# @param [#to_s] name the name of the option.
#
# @param default the default value for the option.
#
# @param [Boolean] boolean whether the option has a boolean value.
#
# @return [void]
#
# @!macro [attach] option
#
# @note this option defaults to $2.
#
# @return the $1 $0 for installation.
#
def self.option(name, default, boolean: true)
name = name.to_s
raise ArgumentError, "The `#{name}` option is already defined" if defaults.key?(name)
defaults[name] = default
attr_accessor name
alias_method "#{name}?", name if boolean
end
# @return [Hash<Symbol,Object>] all known installation options and their
# default values.
#
def self.defaults
@defaults ||= {}
end
# @return [Array<Symbol>] the names of all known installation options.
#
def self.all_options
defaults.keys
end
# Initializes the installation options with a hash of options from a
# Podfile.
#
# @param [Hash] options the options to parse.
#
# @raise [Informative] if `options` contains any unknown keys.
#
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
# @param [Boolean] include_defaults whether values that match the default
# for their option should be included. Defaults to `true`.
#
# @return [Hash] the options, keyed by option name.
#
def to_h(include_defaults: true)
self.class.defaults.reduce(ActiveSupport::HashWithIndifferentAccess.new) do |hash, (option, default)|
value = send(option)
hash[option] = value if include_defaults || value != default
hash
end
end
def ==(other)
other.is_a?(self.class) && to_h == other.to_h
end
alias_method :eql, :==
def hash
to_h.hash
end
option :clean, true
option :deduplicate_targets, true
option :deterministic_uuids, true
option :integrate_targets, true
option :lock_pod_sources, true
module Mixin
module ClassMethods
# Delegates the creation of {#installation_options} to the `Podfile`
# returned by the given block.
#
# @param blk a block that returns the `Podfile` to create
# installation options from.
#
# @return [Void]
#
def delegate_installation_options(&blk)
define_method(:installation_options) do
@installation_options ||= InstallationOptions.from_podfile(instance_eval(&blk))
end
end
# Delegates the installation options attributes directly to
# {#installation_options}.
#
# @return [Void]
#
def delegate_installation_option_attributes!
define_method(:respond_to_missing?) do |name, *args|
installation_options.respond_to?(name, *args) || super
end
define_method(:method_missing) do |name, *args, &blk|
if installation_options.respond_to?(name)
installation_options.send(name, *args, &blk)
else
super
end
end
end
end
# @return [InstallationOptions] The installation options.
#
attr_accessor :installation_options
def self.included(mod)
mod.extend(ClassMethods)
end
end
end
end
end
......@@ -17,14 +17,21 @@ module Pod
#
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.
......@@ -110,7 +117,7 @@ module Pod
# @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)
......@@ -121,7 +128,6 @@ module Pod
Downloader::Request.new(
:spec => root_spec,
:released => released?,
:head => head_pod?,
)
end
......@@ -174,12 +180,8 @@ module Pod
sandbox.local?(root_spec.name)
end
def head_pod?
sandbox.head_pod?(root_spec.name)
end
def released?
!local? && !head_pod? && !predownloaded? && sandbox.specification(root_spec.name) != root_spec
!local? && !predownloaded? && sandbox.specification(root_spec.name) != root_spec
end
def each_source_file(file_accessors, &blk)
......
......@@ -12,6 +12,10 @@ module Pod
#
attr_reader :errors
# @return [Array<String>] any warnings that have occured during the validation
#
attr_reader :warnings
# Initialize a new instance
# @param [Podfile] podfile
# The podfile to validate
......@@ -19,6 +23,7 @@ module Pod
def initialize(podfile)
@podfile = podfile
@errors = []
@warnings = []
@validated = false
end
......@@ -27,6 +32,8 @@ module Pod
#
def validate
validate_pod_directives
validate_no_abstract_only_pods!
validate_dependencies_are_present!
@validated = true
end
......@@ -38,7 +45,7 @@ module Pod
def valid?
validate unless @validated
@validated && errors.size == 0
@validated && errors.empty?
end
# A message describing any errors in the
......@@ -54,6 +61,10 @@ module Pod
errors << error
end
def add_warning(warning)
warnings << warning
end
def validate_pod_directives
dependencies = podfile.target_definitions.flat_map do |_, target|
target.dependencies
......@@ -81,6 +92,36 @@ module Pod
' download strategies. This is not allowed'
end
end
# Warns the user if the podfile is empty.
#
# @note The workspace is created in any case and all the user projects
# are added to it, however the projects are not integrated as
# there is no way to discern between target definitions which are
# empty and target definitions which just serve the purpose to
# wrap other ones. This is not an issue because empty target
# definitions generate empty libraries.
#
# @return [void]
#
def validate_dependencies_are_present!
if podfile.target_definitions.values.all?(&:empty?)
add_warning 'The Podfile does not contain any dependencies.'
end
end
# Verifies that no dependencies in the Podfile will end up not being built
# at all. In other words, all dependencies _must_ belong to a non-abstract
# target, or be inherited by a target where `inheritance == complete`.
#
def validate_no_abstract_only_pods!
all_dependencies = podfile.dependencies
concrete_dependencies = podfile.target_definition_list.reject(&:abstract?).flat_map(&:dependencies).uniq
abstract_only_dependencies = all_dependencies - concrete_dependencies
abstract_only_dependencies.each do |dep|
add_error "The dependency `#{dep}` is not used in any concrete target."
end
end
end
end
end
......@@ -61,7 +61,6 @@ module Pod
def integrate!
create_workspace
integrate_user_targets
warn_about_empty_podfile
warn_about_xcconfig_overrides
save_projects
end
......@@ -152,23 +151,6 @@ module Pod
end
end
# Warns the user if the podfile is empty.
#
# @note The workspace is created in any case and all the user projects
# are added to it, however the projects are not integrated as
# there is no way to discern between target definitions which are
# empty and target definitions which just serve the purpose to
# wrap other ones. This is not an issue because empty target
# definitions generate empty libraries.
#
# @return [void]
#
def warn_about_empty_podfile
if podfile.target_definitions.values.all?(&:empty?)
UI.warn '[!] The Podfile does not contain any dependencies.'
end
end
IGNORED_KEYS = %w(CODE_SIGN_IDENTITY).freeze
INHERITED_FLAGS = %w($(inherited) ${inherited}).freeze
......@@ -234,7 +216,7 @@ module Pod
end
def targets_to_integrate
targets.reject { |target| target.target_definition.empty? }
targets.reject { |target| target.target_definition.abstract? }
end
# Prints a warning informing the user that a build configuration of
......
......@@ -85,7 +85,7 @@ module Pod
end
if existing && existing != file_ref
if existing.real_path.to_path.start_with?(pod_bundle.support_files_dir.to_path)
if existing.real_path.to_path.start_with?(pod_bundle.sandbox.root.to_path << '/')
set_base_configuration_reference.call
elsif !xcconfig_includes_target_xcconfig?(config.base_configuration_reference, path)
UI.warn 'CocoaPods did not set the base configuration of your ' \
......@@ -93,7 +93,7 @@ module Pod
'config set. In order for CocoaPods integration to work at ' \
'all, please either set the base configurations of the target ' \
"`#{target.name}` to `#{path}` or include the `#{path}` in your " \
'build configuration.'
"build configuration (#{UI.path(existing.real_path)})."
end
elsif config.base_configuration_reference.nil? || file_ref.nil?
set_base_configuration_reference.call
......
......@@ -60,11 +60,7 @@ module Pod
end
end
@activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies)
specs_by_target.tap do |specs_by_target|
specs_by_target.values.flatten.each do |spec|
sandbox.store_head_pod(spec.name) if spec.version.head?
end
end
specs_by_target
rescue Molinillo::ResolverError => e
handle_resolver_error(e)
end
......@@ -185,7 +181,7 @@ module Pod
end
requirement_satisfied && !(
spec.version.prerelease? &&
existing_vertices.flat_map(&:requirements).none? { |r| r.prerelease? || r.external_source || r.head? }
existing_vertices.flat_map(&:requirements).none? { |r| r.prerelease? || r.external_source }
) && spec_is_platform_compatible?(activated, requirement, spec)
end
......@@ -304,9 +300,6 @@ module Pod
else
set = create_set_from_sources(dependency)
end
if set && dependency.head?
set = Specification::Set::Head.new(set.specification)
end
cached_sets[name] = set
unless set
raise Molinillo::NoSuchDependencyError.new(dependency) # rubocop:disable Style/RaiseArgs
......@@ -390,8 +383,7 @@ module Pod
elsif (conflict.possibility && conflict.possibility.version.prerelease?) &&
(conflict.requirement && !(
conflict.requirement.prerelease? ||
conflict.requirement.external_source ||
conflict.requirement.head?)
conflict.requirement.external_source)
)
# Conflict was caused by not specifying an explicit version for the requirement #[name],
# and there is no available stable version satisfying constraints for the requirement.
......
......@@ -59,7 +59,6 @@ module Pod
@root = Pathname.new(root).realpath
@public_headers = HeadersStore.new(self, 'Public')
@predownloaded_pods = []
@head_pods = []
@checkout_sources = {}
@development_pods = {}
@pods_with_absolute_path = []
......@@ -313,37 +312,6 @@ module Pod
#--------------------------------------#
# Marks a Pod as head.
#
# @param [String] name
# The name of the Pod.
#
# @return [void]
#
def store_head_pod(name)
root_name = Specification.root_name(name)
head_pods << root_name
end
# @return [Array<String>] The names of the pods that have been
# marked as head.
#
attr_reader :head_pods
# Checks if a Pod should attempt to use the head source of the git repo.
#
# @param [String] name
# The name of the Pod.
#
# @return [Bool] Whether the Pod has been marked as head.
#
def head_pod?(name)
root_name = Specification.root_name(name)
head_pods.include?(root_name)
end
#--------------------------------------#
# Stores the local path of a Pod.
#
# @param [String] name
......
......@@ -17,6 +17,7 @@ module Pod
@target_definition = target_definition
@sandbox = sandbox
@pod_targets = []
@search_paths_aggregate_targets = []
@file_accessors = []
@xcconfigs = {}
end
......@@ -103,6 +104,11 @@ module Pod
#
attr_accessor :pod_targets
# @return [Array<AggregateTarget>] The aggregate targets whose pods this
# target must be able to import, but will not directly link against.
#
attr_accessor :search_paths_aggregate_targets
# @param [String] build_configuration The build configuration for which the
# the pod targets should be returned.
#
......
......@@ -354,9 +354,7 @@ module Pod
@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
......@@ -664,7 +662,9 @@ module Pod
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)
platform(platform_name, deployment_target)
if local
......@@ -674,6 +674,7 @@ module Pod
end
end
end
end
# Parse the xcode build output to identify the lines which are relevant
# to the linter.
......
Subproject commit b464161555947e7992606e0b186c1e8078d36f7f
Subproject commit 75f5c4b33eb3b371a4d383b007a3bfd2933563e3
......@@ -34,6 +34,7 @@
A346497C14F9BE9A0080D870 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A346497A14F9BE9A0080D870 /* InfoPlist.strings */; };
A346497E14F9BE9A0080D870 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A346497D14F9BE9A0080D870 /* main.m */; };
A346498214F9BE9A0080D870 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A346498114F9BE9A0080D870 /* AppDelegate.m */; };
C0C495361B9E5C47004F9854 /* SampleProjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C0C495351B9E5C47004F9854 /* SampleProjectTests.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
......@@ -44,6 +45,13 @@
remoteGlobalIDString = 51E94E0F164472080035348C;
remoteInfo = "Sample Lib";
};
C0C495381B9E5C47004F9854 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A346496414F9BE990080D870 /* Project object */;
proxyType = 1;
remoteGlobalIDString = A346496C14F9BE9A0080D870;
remoteInfo = SampleProject;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
......@@ -79,6 +87,9 @@
A346497F14F9BE9A0080D870 /* SampleProject-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SampleProject-Prefix.pch"; sourceTree = "<group>"; };
A346498014F9BE9A0080D870 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
A346498114F9BE9A0080D870 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
C0C495331B9E5C47004F9854 /* SampleProjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleProjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C0C495351B9E5C47004F9854 /* SampleProjectTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleProjectTests.m; sourceTree = "<group>"; };
C0C495371B9E5C47004F9854 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -110,6 +121,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
C0C495301B9E5C47004F9854 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
......@@ -157,6 +175,7 @@
A346497714F9BE9A0080D870 /* SampleProject */,
51075D4F1521D0C100E39B41 /* TestRunner */,
29FAC56B1B1F0502002187FA /* CLITool */,
C0C495341B9E5C47004F9854 /* SampleProjectTests */,
A346497014F9BE9A0080D870 /* Frameworks */,
A346496E14F9BE9A0080D870 /* Products */,
);
......@@ -168,6 +187,7 @@
A346496D14F9BE9A0080D870 /* SampleProject.app */,
51075D4A1521D0C100E39B41 /* TestRunner.app */,
29FAC56A1B1F0502002187FA /* CLITool */,
C0C495331B9E5C47004F9854 /* SampleProjectTests.xctest */,
);
name = Products;
sourceTree = "<group>";
......@@ -203,6 +223,15 @@
name = "Supporting Files";
sourceTree = "<group>";
};
C0C495341B9E5C47004F9854 /* SampleProjectTests */ = {
isa = PBXGroup;
children = (
C0C495351B9E5C47004F9854 /* SampleProjectTests.m */,
C0C495371B9E5C47004F9854 /* Info.plist */,
);
path = SampleProjectTests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
......@@ -257,18 +286,41 @@
productReference = A346496D14F9BE9A0080D870 /* SampleProject.app */;
productType = "com.apple.product-type.application";
};
C0C495321B9E5C47004F9854 /* SampleProjectTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = C0C4953A1B9E5C47004F9854 /* Build configuration list for PBXNativeTarget "SampleProjectTests" */;
buildPhases = (
C0C4952F1B9E5C47004F9854 /* Sources */,
C0C495301B9E5C47004F9854 /* Frameworks */,
C0C495311B9E5C47004F9854 /* Resources */,
);
buildRules = (
);
dependencies = (
C0C495391B9E5C47004F9854 /* PBXTargetDependency */,
);
name = SampleProjectTests;
productName = SampleProjectTests;
productReference = C0C495331B9E5C47004F9854 /* SampleProjectTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
A346496414F9BE990080D870 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0630;
ORGANIZATIONNAME = "LJR Software Limited";
TargetAttributes = {
29FAC5691B1F0502002187FA = {
CreatedOnToolsVersion = 6.3.2;
};
C0C495321B9E5C47004F9854 = {
CreatedOnToolsVersion = 7.0;
TestTargetID = A346496C14F9BE9A0080D870;
};
};
};
buildConfigurationList = A346496714F9BE990080D870 /* Build configuration list for PBXProject "SampleProject" */;
......@@ -293,6 +345,7 @@
51075D491521D0C100E39B41 /* TestRunner */,
51D6A8AB16C445B800E174E1 /* AggregateTarget */,
29FAC5691B1F0502002187FA /* CLITool */,
C0C495321B9E5C47004F9854 /* SampleProjectTests */,
);
};
/* End PBXProject section */
......@@ -324,6 +377,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
C0C495311B9E5C47004F9854 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
......@@ -353,8 +413,24 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
C0C4952F1B9E5C47004F9854 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C0C495361B9E5C47004F9854 /* SampleProjectTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
C0C495391B9E5C47004F9854 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A346496C14F9BE9A0080D870 /* SampleProject */;
targetProxy = C0C495381B9E5C47004F9854 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
51075D521521D0C100E39B41 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
......@@ -721,6 +797,101 @@
};
name = Release;
};
C0C4953B1B9E5C47004F9854 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_TESTABILITY = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SampleProjectTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SampleProjectTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SampleProject.app/SampleProject";
};
name = Debug;
};
C0C4953C1B9E5C47004F9854 /* Test */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SampleProjectTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SampleProjectTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SampleProject.app/SampleProject";
};
name = Test;
};
C0C4953D1B9E5C47004F9854 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SampleProjectTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SampleProjectTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SampleProject.app/SampleProject";
};
name = Release;
};
C0C4953E1B9E5C47004F9854 /* App Store */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
INFOPLIST_FILE = SampleProjectTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SampleProjectTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SampleProject.app/SampleProject";
};
name = "App Store";
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
......@@ -733,6 +904,7 @@
29FAC5711B1F0502002187FA /* App Store */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
51075D5B1521D0C100E39B41 /* Build configuration list for PBXNativeTarget "TestRunner" */ = {
isa = XCConfigurationList;
......@@ -778,6 +950,16 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C0C4953A1B9E5C47004F9854 /* Build configuration list for PBXNativeTarget "SampleProjectTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C0C4953B1B9E5C47004F9854 /* Debug */,
C0C4953C1B9E5C47004F9854 /* Test */,
C0C4953D1B9E5C47004F9854 /* Release */,
C0C4953E1B9E5C47004F9854 /* App Store */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = A346496414F9BE990080D870 /* Project object */;
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
//
// SampleProjectTests.m
// SampleProjectTests
//
// Created by Samuel Giddins on 9/7/15.
// Copyright © 2015 LJR Software Limited. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface SampleProjectTests : XCTestCase
@end
@implementation SampleProjectTests
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
@end
......@@ -53,25 +53,5 @@ module Pod
`git log --pretty=oneline`.strip.split("\n").size.should > 1
end
end
before do
FileUtils.rm_rf(test_repo_path)
set_up_old_test_repo
config.repos_dir = SpecHelper.temporary_directory + 'cocoapods/repos'
Command::Setup.any_instance.stubs(:old_master_repo_dir).returns(SpecHelper.temporary_directory + 'cocoapods/master')
end
it 'migrates repos from the old directory structure to the new one' do
source = SpecHelper.temporary_directory + 'cocoapods/master'
target = config.repos_dir + 'master'
source.should.exist?
target.should.not.exist?
run_command('setup')
source.should.not.exist?
target.should.exist?
end
end
end
......@@ -44,9 +44,12 @@ $:.unshift((ROOT + 'spec').to_s)
require 'rubygems'
require 'bundler/setup'
require 'pretty_bacon'
require 'colored'
require 'clintegracon'
require 'cocoapods-core/yaml_helper'
require 'fileutils'
require 'integration/file_tree'
require 'integration/xcodeproj_project_yaml'
......@@ -78,11 +81,19 @@ CLIntegracon.configure do |c|
end
# Register special handling for YAML files
c.transform_produced '**/{Podfile,Manifest}.lock' do |path|
# Remove CocoaPods version
c.transform_produced %r{(^|/)(Podfile|Manifest).lock$} do |path|
# Remove CocoaPods version & Podfile checksum
yaml = YAML.load(path.read)
yaml.delete('COCOAPODS')
path.open('w') { |f| f << YAML.dump(yaml) }
yaml.delete('PODFILE CHECKSUM')
keys_hint = [
'PODS',
'DEPENDENCIES',
'EXTERNAL SOURCES',
'CHECKOUT OPTIONS',
'SPEC CHECKSUMS',
]
path.open('w') { |f| f << Pod::YAMLHelper.convert_hash(yaml, keys_hint, "\n\n") }
end
# So we don't need to compare them directly
......@@ -151,6 +162,22 @@ describe_cli 'pod' do
# Test installation with no integration
# Test subspecs inheritance
#--------------------------------------#
describe 'Pod init' do
describe 'Initializes a Podfile with a single platform' do
behaves_like cli_spec 'init_single_platform',
'init'
end
end
#--------------------------------------#
describe 'Integrates a project with an empty Podfile with CocoaPods' do
behaves_like cli_spec 'install_no_dependencies',
'install --no-repo-update'
end
describe 'Integrates a project with CocoaPods' do
behaves_like cli_spec 'install_new',
'install --no-repo-update'
......@@ -298,13 +325,4 @@ describe_cli 'pod' do
end
#--------------------------------------#
describe 'Pod init' do
describe 'Initializes a Podfile with a single platform' do
behaves_like cli_spec 'init_single_platform',
'init'
end
end
#--------------------------------------#
end
......@@ -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
......
......@@ -15,16 +15,6 @@ module Pod
path.should.exist?
end
it 'supports the deprecated local key' do
params = { :local => fixture('integration/Reachability') }
dependency = Dependency.new('Reachability', params)
podfile_path = fixture('integration/Podfile')
@subject = ExternalSources.from_dependency(dependency, podfile_path)
@subject.fetch(config.sandbox)
path = config.sandbox.specifications_root + 'Reachability.podspec.json'
path.should.exist?
end
it 'returns the description' do
@subject.description.should.match /from `.*integration\/Reachability`/
end
......
......@@ -19,12 +19,6 @@ module Pod
klass.should == @subject::PathSource
end
it 'supports a path source specified with the legacy :local key' do
dep = Dependency.new('Reachability', :local => '')
klass = @subject.from_dependency(dep, nil).class
klass.should == @subject::PathSource
end
it 'supports all the strategies implemented by the downloader' do
[:git, :svn, :hg, :bzr, :http].each do |strategy|
dep = Dependency.new('Reachability', strategy => '')
......
......@@ -16,13 +16,6 @@ module Pod
@generator = Generator::InfoPlistFile.new(pod_target)
end
it 'handles when the version is HEAD' do
version = Version.new('0.2.0')
version.head = true
@root_spec.stubs(:version).returns(version)
@generator.target_version.should == '0.2.0'
end
it 'handles when the version is more than 3 numeric parts' do
version = Version.new('0.2.0.1')
@root_spec.stubs(:version).returns(version)
......
......@@ -19,26 +19,26 @@ module Pod
it 'raises if no name is given' do
should.raise ArgumentError do
@hooks_manager.register(nil) {}
@hooks_manager.register('name', nil) {}
end
end
it 'raises if no block is given' do
should.raise ArgumentError do
@hooks_manager.register(:post_install)
@hooks_manager.register('name', :post_install)
end
end
it 'warns if no plugin name is given' do
@hooks_manager.register(:post_install) {}
UI.warnings.should.match /hooks without.*deprecated/
UI.warnings.should.match /#{__FILE__}/
it 'raises if no plugin name is given' do
should.raise ArgumentError do
@hooks_manager.register(nil, :post_install) {}
end
end
end
describe 'run' do
it 'invokes the hooks' do
@hooks_manager.register(:post_install) do |_options|
@hooks_manager.register('plugin', :post_install) do |_options|
true.should.be.true
end
@hooks_manager.run(:post_install, Object.new)
......@@ -51,7 +51,7 @@ module Pod
end
it 'handles the case that no listeners have registered for a name' do
@hooks_manager.register(:post_install) do |_options|
@hooks_manager.register('plugin', :post_install) do |_options|
true.should.be.true
end
should.not.raise do
......@@ -106,7 +106,7 @@ module Pod
it 'prints a message in verbose mode when any hooks are run' do
config.verbose = true
@hooks_manager.register(:post_install) {}
@hooks_manager.register('plugin', :post_install) {}
@hooks_manager.run(:post_install, Object.new)
UI.output.should.match /- Running post install hooks/
end
......
......@@ -83,24 +83,6 @@ module Pod
@sandbox.stubs(:predownloaded?).returns(true)
@analyzer.send(:pod_changed?, 'BananaLib').should == true
end
it "considers a changed Pod whose head state doesn't match" do
@sandbox.stubs(:head_pod?).returns(true)
@analyzer.send(:pod_changed?, 'BananaLib').should == true
end
it 'considers changed a Pod whose specification is in head mode if in update mode' do
@sandbox.stubs(:head_pod?).returns(true)
@analyzer.stubs(:update_mode?).returns(true)
@analyzer.send(:pod_changed?, 'BananaLib').should == true
end
it "doesn't consider a changed Pod whose specification is in head mode if not in update mode" do
@sandbox.stubs(:head_pod?).returns(true)
@analyzer.stubs(:sandbox_head_version?).returns(true)
@analyzer.stubs(:update_mode?).returns(false)
@analyzer.send(:pod_changed?, 'BananaLib').should == false
end
end
#-------------------------------------------------------------------------#
......
......@@ -58,8 +58,7 @@ module Pod
describe '#compute_targets' do
it 'returns the targets specified in the target definition' do
target_definition = Podfile::TargetDefinition.new(:default, nil)
target_definition.link_with = ['UserTarget']
target_definition = Podfile::TargetDefinition.new('UserTarget', nil)
user_project = Xcodeproj::Project.new('path')
user_project.new_target(:application, 'FirstTarget', :ios)
user_project.new_target(:application, 'UserTarget', :ios)
......@@ -70,54 +69,44 @@ module Pod
end
it 'raises if it is unable to find the targets specified by the target definition' do
target_definition = Podfile::TargetDefinition.new(:default, nil)
target_definition.link_with = %w(UserTarget AnotherUserTarget)
target_definition = Podfile::TargetDefinition.new('UserTarget', nil)
user_project = Xcodeproj::Project.new('path')
target_inspector = TargetInspector.new(target_definition, config.installation_root)
e = lambda { target_inspector.send(:compute_targets, user_project) }.should.raise Informative
e.message.should.match /Unable to find the targets named `UserTarget` and `AnotherUserTarget`/
e.message.should.match /Unable to find a target named `UserTarget`/
end
it 'returns the target with the same name of the target definition' do
it 'suggests project native target names if the target cannot be found' do
target_definition = Podfile::TargetDefinition.new('UserTarget', nil)
user_project = Xcodeproj::Project.new('path')
user_project.new_target(:application, 'FirstTarget', :ios)
user_project.new_target(:application, 'UserTarget', :ios)
target_inspector = TargetInspector.new(target_definition, config.installation_root)
targets = target_inspector.send(:compute_targets, user_project)
targets.map(&:name).should == ['UserTarget']
end
it 'raises if the name of the target definition does not match any file' do
target_definition = Podfile::TargetDefinition.new('UserTarget', nil)
user_project = Xcodeproj::Project.new('path')
user_project.new_target(:application, 'SecondTarget', :ios)
user_project.new_target(:application, 'ThirdTarget', :ios)
target_inspector = TargetInspector.new(target_definition, config.installation_root)
e = lambda { target_inspector.send(:compute_targets, user_project) }.should.raise Informative
e.message.should.match /Unable to find a target named/
e.message.should.include 'did find `FirstTarget`, `SecondTarget`, and `ThirdTarget`.'
end
it 'returns the first target of the project if the target definition is named default' do
target_definition = Podfile::TargetDefinition.new('Pods', nil)
target_definition.link_with_first_target = true
it 'returns the target with the same name of the target definition' do
target_definition = Podfile::TargetDefinition.new('UserTarget', nil)
user_project = Xcodeproj::Project.new('path')
user_project.new_target(:application, 'FirstTarget', :ios)
user_project.new_target(:application, 'UserTarget', :ios)
target_inspector = TargetInspector.new(target_definition, config.installation_root)
targets = target_inspector.send(:compute_targets, user_project)
targets.map(&:name).should == ['FirstTarget']
targets.map(&:name).should == ['UserTarget']
end
it 'raises if the default target definition cannot be linked because there are no user targets' do
target_definition = Podfile::TargetDefinition.new(:default, nil)
it 'raises if the name of the target definition does not match any file' do
target_definition = Podfile::TargetDefinition.new('UserTarget', nil)
user_project = Xcodeproj::Project.new('path')
target_inspector = TargetInspector.new(target_definition, config.installation_root)
e = lambda { target_inspector.send(:compute_targets, user_project) }.should.raise Informative
e.message.should.match /Unable to find a target/
e.message.should.match /Unable to find a target named/
end
end
......
......@@ -7,16 +7,21 @@ module Pod
@podfile = Pod::Podfile.new do
platform :ios, '6.0'
xcodeproj 'SampleProject/SampleProject'
target 'SampleProject' do
pod 'JSONKit', '1.5pre'
pod 'AFNetworking', '1.0.1'
pod 'SVPullToRefresh', '0.4'
pod 'libextobjc/EXTKeyPathCoding', '0.2.3'
target 'TestRunner' do
inherit! :search_paths
pod 'libextobjc/EXTKeyPathCoding', '0.2.3'
pod 'libextobjc/EXTSynthesize', '0.2.3'
end
end
end
hash = {}
hash['PODS'] = ['JSONKit (1.5pre)', 'NUI (0.2.0)', 'SVPullToRefresh (0.4)']
......@@ -131,9 +136,9 @@ module Pod
'JSONKit',
'AFNetworking',
'SVPullToRefresh',
'Pods-libextobjc',
'Pods-SampleProject-libextobjc',
].sort
target.support_files_dir.should == config.sandbox.target_support_files_dir('Pods')
target.support_files_dir.should == config.sandbox.target_support_files_dir('Pods-SampleProject')
target.pod_targets.map(&:archs).uniq.should == [[]]
......@@ -187,6 +192,7 @@ module Pod
source SpecHelper.test_repo_url
platform :ios, '6.0'
xcodeproj 'SampleProject/SampleProject'
target 'SampleProject' do
pod 'BananaLib'
pod 'monkey'
......@@ -195,14 +201,15 @@ module Pod
pod 'monkey'
end
end
end
analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile)
analyzer.analyze
analyzer.analyze.targets.flat_map { |at| at.pod_targets.map { |pt| "#{at.name}/#{pt.name}" } }.sort.should == %w(
Pods/BananaLib
Pods/monkey
Pods-TestRunner/BananaLib
Pods-TestRunner/monkey
Pods-SampleProject-TestRunner/BananaLib
Pods-SampleProject-TestRunner/monkey
Pods-SampleProject/BananaLib
Pods-SampleProject/monkey
).sort
end
......@@ -214,10 +221,12 @@ module Pod
pod 'BananaLib'
pod 'monkey'
target 'SampleProject' do
target 'TestRunner' do
pod 'BananaLib'
pod 'monkey'
end
end
target 'CLITool' do
platform :osx, '10.10'
......@@ -228,17 +237,17 @@ module Pod
analyzer.analyze
analyzer.analyze.targets.flat_map { |at| at.pod_targets.map { |pt| "#{at.name}/#{pt.name}" } }.sort.should == %w(
Pods/Pods-BananaLib
Pods/Pods-monkey
Pods-TestRunner/Pods-TestRunner-BananaLib
Pods-TestRunner/Pods-TestRunner-monkey
Pods-CLITool/Pods-CLITool-monkey
Pods-SampleProject-TestRunner/Pods-SampleProject-TestRunner-BananaLib
Pods-SampleProject-TestRunner/Pods-SampleProject-TestRunner-monkey
Pods-SampleProject/Pods-SampleProject-BananaLib
Pods-SampleProject/Pods-SampleProject-monkey
).sort
end
end
it 'generates the integration library appropriately if the installation will not integrate' do
config.integrate_targets = false
@analyzer.installation_options.integrate_targets = false
target = @analyzer.analyze.targets.first
target.client_root.should == config.installation_root
......@@ -253,11 +262,11 @@ module Pod
aggregate = Pod::Source::Aggregate.new(repos)
Pod::SourcesManager.stubs(:aggregate).returns(aggregate)
aggregate.sources.first.stubs(:url).returns(SpecHelper.test_repo_url)
config.integrate_targets = false
end
it 'does not require a platform for an empty target' do
podfile = Pod::Podfile.new do
install! 'cocoapods', :integrate_targets => false
source SpecHelper.test_repo_url
xcodeproj 'SampleProject/SampleProject'
target 'TestRunner' do
......@@ -272,6 +281,7 @@ module Pod
it 'does not raise if a target with dependencies inherits the platform from its parent' do
podfile = Pod::Podfile.new do
install! 'cocoapods', :integrate_targets => false
source SpecHelper.test_repo_url
xcodeproj 'SampleProject/SampleProject'
platform :osx
......@@ -286,6 +296,7 @@ module Pod
it 'raises if a target with dependencies does not have a platform' do
podfile = Pod::Podfile.new do
install! 'cocoapods', :integrate_targets => false
source SpecHelper.test_repo_url
xcodeproj 'SampleProject/SampleProject'
target 'TestRunner' do
......@@ -335,9 +346,11 @@ module Pod
podfile = Podfile.new do
platform :ios, '8.0'
xcodeproj 'SampleProject/SampleProject'
target 'SampleProject' do
pod 'AFNetworking'
pod 'AFNetworkActivityLogger'
end
end
hash = {}
hash['PODS'] = [
{ 'AFNetworkActivityLogger (2.0.3)' => ['AFNetworking/NSURLConnection (~> 2.0)', 'AFNetworking/NSURLSession (~> 2.0)'] },
......@@ -367,8 +380,10 @@ module Pod
podfile = Podfile.new do
platform :ios, '8.0'
xcodeproj 'SampleProject/SampleProject'
target 'SampleProject' do
pod 'ARAnalytics/Mixpanel'
end
end
hash = {}
hash['PODS'] = ['ARAnalytics/CoreIOS (2.8.0)', { 'ARAnalytics/Mixpanel (2.8.0)' => ['ARAnlytics/CoreIOS', 'Mixpanel'] }, 'Mixpanel (2.5.1)']
hash['DEPENDENCIES'] = %w(ARAnalytics/Mixpanel)
......@@ -454,9 +469,6 @@ module Pod
'libextobjc/EXTKeyPathCoding (0.2.3)',
]
@analyzer.analyze.targets[1].pod_targets.map(&:specs).flatten.map(&:to_s).should == [
'AFNetworking (1.0.1)',
'JSONKit (1.5pre)',
'SVPullToRefresh (0.4)',
'libextobjc/EXTKeyPathCoding (0.2.3)',
'libextobjc/EXTSynthesize (0.2.3)',
]
......@@ -469,9 +481,11 @@ module Pod
source 'https://github.com/CocoaPods/Specs.git'
xcodeproj 'SampleProject/SampleProject'
platform :ios, '8.0'
target 'SampleProject' do
pod 'RestKit', '~> 0.23.0'
pod 'RestKit', '<= 0.23.2'
end
end
analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile, nil)
analyzer.analyze
......@@ -542,9 +556,11 @@ module Pod
source 'https://github.com/CocoaPods/Specs.git'
xcodeproj 'SampleProject/SampleProject'
platform :ios
target 'SampleProject' do
pod 'SEGModules', :git => 'https://github.com/segiddins/SEGModules.git'
pod 'SEGModules', :git => 'https://github.com/segiddins/Modules.git'
end
end
analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile, nil)
e = should.raise(Informative) { analyzer.analyze }
......@@ -559,9 +575,11 @@ module Pod
source 'https://github.com/CocoaPods/Specs.git'
xcodeproj 'SampleProject/SampleProject'
platform :ios
target 'SampleProject' do
pod 'RestKit/Core', :git => 'https://github.com/RestKit/RestKit.git'
pod 'RestKit', :git => 'https://github.com/segiddins/RestKit.git'
end
end
analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile, nil)
e = should.raise(Informative) { analyzer.analyze }
......@@ -576,9 +594,11 @@ module Pod
source 'https://github.com/CocoaPods/Specs.git'
xcodeproj 'SampleProject/SampleProject'
platform :ios
target 'SampleProject' do
pod 'RestKit', :git => 'https://github.com/RestKit/RestKit.git'
pod 'RestKit', '~> 0.23.0'
end
end
analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile, nil)
e = should.raise(Informative) { analyzer.analyze }
......@@ -588,11 +608,39 @@ module Pod
end
end
describe 'podfile validation' do
before do
@sandbox = stub('Sandbox')
@podfile = stub('Podfile')
@analyzer = Installer::Analyzer.new(@sandbox, @podfile)
end
it 'raises when validating errors' do
Installer::PodfileValidator.any_instance.expects(:validate)
Installer::PodfileValidator.any_instance.expects(:valid?).returns(false)
Installer::PodfileValidator.any_instance.stubs(:errors).returns(['ERROR'])
should.raise(Informative) { @analyzer.send(:validate_podfile!) }.
message.should.match /ERROR/
end
it 'warns when validating has warnings' do
Installer::PodfileValidator.any_instance.expects(:validate)
Installer::PodfileValidator.any_instance.expects(:valid?).returns(true)
Installer::PodfileValidator.any_instance.stubs(:warnings).returns(['The Podfile does not contain any dependencies.'])
@analyzer.send(:validate_podfile!)
UI.warnings.should == "The Podfile does not contain any dependencies.\n"
end
end
describe 'using lockfile checkout options' do
before do
@podfile = Pod::Podfile.new do
target 'SampleProject' do
pod 'BananaLib', :git => 'example.com'
end
end
@dependency = @podfile.dependencies.first
@lockfile_checkout_options = { :git => 'example.com', :commit => 'commit' }
......@@ -639,6 +687,7 @@ module Pod
ExternalSources.stubs(:from_params).with(@lockfile_checkout_options, @dependency, @podfile.defined_in_file).returns(downloader)
downloader.expects(:fetch)
downloader.expects(:can_cache=).with(true).once
@analyzer.send(:fetch_external_sources)
end
......@@ -650,6 +699,7 @@ module Pod
ExternalSources.stubs(:from_params).with(@lockfile_checkout_options, @dependency, @podfile.defined_in_file).returns(downloader)
downloader.expects(:fetch)
downloader.expects(:can_cache=).with(true).once
@analyzer.send(:fetch_external_sources)
end
......@@ -660,6 +710,7 @@ module Pod
ExternalSources.stubs(:from_params).with(@dependency.external_source, @dependency, @podfile.defined_in_file).returns(downloader)
downloader.expects(:fetch)
downloader.expects(:can_cache=).with(true).once
@analyzer.send(:fetch_external_sources)
end
......@@ -671,6 +722,7 @@ module Pod
ExternalSources.stubs(:from_params).with(@dependency.external_source, @dependency, @podfile.defined_in_file).returns(downloader)
downloader.expects(:fetch)
downloader.expects(:can_cache=).with(true).once
@analyzer.send(:fetch_external_sources)
end
......@@ -682,6 +734,20 @@ module Pod
ExternalSources.stubs(:from_params).with(@dependency.external_source, @dependency, @podfile.defined_in_file).returns(downloader)
downloader.expects(:fetch)
downloader.expects(:can_cache=).with(true).once
@analyzer.send(:fetch_external_sources)
end
it 'does not use the cache when the podfile instructs not to clean' do
@analyzer.result.podfile_state.unchanged << 'BananaLib'
@sandbox_manifest.send(:checkout_options_data).delete('BananaLib')
downloader = stub('DownloaderSource')
ExternalSources.stubs(:from_params).with(@lockfile_checkout_options, @dependency, @podfile.defined_in_file).returns(downloader)
downloader.expects(:fetch)
downloader.expects(:can_cache=).with(false).once
@analyzer.installation_options.clean = false
@analyzer.send(:fetch_external_sources)
end
......
require File.expand_path('../../../spec_helper', __FILE__)
module Pod
describe Installer::InstallationOptions do
describe 'registered options' do
{
'clean' => true,
'deduplicate_targets' => true,
'deterministic_uuids' => true,
'integrate_targets' => true,
'lock_pod_sources' => true,
}.each do |option, default|
it "includes `#{option}` defaulting to `#{default}`" do
Installer::InstallationOptions.defaults.fetch(option).should == default
Installer::InstallationOptions.new.send(option).should == default
end
end
end
describe '.from_podfile' do
it 'raises for a non-cocoapods install' do
podfile = Podfile.new { install! 'foo', :key => 'value' }
exception = should.raise(Informative) { Installer::InstallationOptions.from_podfile(podfile) }
exception.message.should.include 'Currently need to specify a `cocoapods` install, you chose `foo`.'
end
it 'parses the name in a case-insensitive manner' do
podfile = Podfile.new { install! 'CoCoApOdS' }
should.not.raise(Informative) { Installer::InstallationOptions.from_podfile(podfile) }
end
it 'uses the installation method options to create the options' do
options = { :integrate_targets => false }
podfile = Podfile.new { install! 'cocoapods', options }
installation_options = Installer::InstallationOptions.from_podfile(podfile)
installation_options.should == Installer::InstallationOptions.new(options)
end
end
describe '#initialize' do
it 'uses all defaults when no options are specified' do
Installer::InstallationOptions.new.to_h(:include_defaults => false).should.be.empty
end
it 'sets the values as specified in the options' do
installation_options = Installer::InstallationOptions.new(:deterministic_uuids => false)
installation_options.deterministic_uuids.should.be.false
end
it 'raises when unknown keys are encountered' do
exception = should.raise(Informative) { Installer::InstallationOptions.new(:a => 'a', :b => 'b', :c => 'c') }
exception.message.should.include 'Unknown installation options: a, b, and c.'
end
end
describe '#to_h' do
it 'includes all options by default' do
installation_options = Installer::InstallationOptions.new(:deterministic_uuids => false)
installation_options.to_h.should == {
'clean' => true,
'deduplicate_targets' => true,
'deterministic_uuids' => false,
'integrate_targets' => true,
'lock_pod_sources' => true,
}
end
it 'removes default values when specified' do
installation_options = Installer::InstallationOptions.new(:deterministic_uuids => false)
installation_options.to_h(:include_defaults => false).should == {
'deterministic_uuids' => false,
}
end
end
end
end
......@@ -23,15 +23,6 @@ module Pod
pod_folder.should.exist
end
it 'downloads the head source even if a specific source is present specified source' do
config.sandbox.store_head_pod('BananaLib')
@spec.source = { :git => SpecHelper.fixture('banana-lib'), :tag => 'v1.0' }
@installer.install!
@installer.specific_source[:commit].should == FIXTURE_HEAD
pod_folder = config.sandbox.pod_dir('BananaLib')
pod_folder.should.exist
end
it 'returns the checkout options of the downloader if any' do
@spec.source = { :git => SpecHelper.fixture('banana-lib'), :branch => 'topicbranch' }
@installer.install!
......@@ -39,27 +30,6 @@ module Pod
pod_folder = config.sandbox.pod_dir('BananaLib')
pod_folder.should.exist
end
it 'stores the checkout options in the sandbox' do
config.sandbox.store_head_pod('BananaLib')
@spec.source = { :git => SpecHelper.fixture('banana-lib'), :tag => 'v1.0' }
@installer.install!
sources = @installer.sandbox.checkout_sources
sources.should == { 'BananaLib' => {
:git => SpecHelper.fixture('banana-lib'),
:commit => FIXTURE_HEAD },
}
end
it 'fails when using :head for http source' do
config.sandbox.store_head_pod('BananaLib')
@spec.source = { :http => 'http://dl.google.com/googleadmobadssdk/googleadmobsearchadssdkios.zip' }
@spec.source_files = 'GoogleAdMobSearchAdsSDK/*.h'
Pod::Downloader::Http.any_instance.stubs(:download_head)
should.raise Informative do
@installer.install!
end.message.should.match /does not support the :head option, as it uses a Http source./
end
end
#--------------------------------------#
......
......@@ -5,6 +5,7 @@ module Pod
describe 'podspec/path in combination with other download strategies' do
it 'validates that podspec is not used in combination with other download strategies' do
podfile = Pod::Podfile.new do
abstract!(false)
pod 'JSONKit', :podspec => 'https://raw.githubusercontent.com/CocoaPods/Specs/master/Specs/JSONKit/1.5pre/JSONKit.podspec.json',
:git => 'git@github.com:johnezang/JSONKit.git'
end
......@@ -19,6 +20,7 @@ module Pod
it 'validates that path is not used in combination with other download strategies' do
podfile = Pod::Podfile.new do
abstract!(false)
pod 'JSONKit', :path => './JSONKit/1.5pre/JSONKit.podspec.json',
:git => 'git@github.com:johnezang/JSONKit.git'
end
......@@ -33,6 +35,7 @@ module Pod
it 'validates when calling `valid?` before calling `validate`' do
podfile = Pod::Podfile.new do
abstract!(false)
pod 'JSONKit', :path => './JSONKit/1.5pre/JSONKit.podspec.json',
:git => 'git@github.com:johnezang/JSONKit.git'
end
......@@ -47,6 +50,7 @@ module Pod
describe 'multiple download strategies' do
it 'validates that only one download strategy is specified' do
podfile = Pod::Podfile.new do
abstract!(false)
pod 'JSONKit', :svn => 'svn.example.com/JSONKit',
:git => 'git@github.com:johnezang/JSONKit.git'
end
......@@ -58,5 +62,125 @@ module Pod
validator.errors[0].should.match /The dependency `JSONKit` specifies more than one/
end
end
describe 'empty podfiles' do
it 'warns if the podfile does not contain any dependency' do
podfile = Pod::Podfile.new
validator = Installer::PodfileValidator.new(podfile)
validator.validate
validator.should.be.valid
validator.errors.should.be.empty
validator.warnings.should == ['The Podfile does not contain any dependencies.']
end
end
describe 'abstract-only dependencies' do
it 'errors when there is only a root target' do
podfile = Pod::Podfile.new do
pod 'Alamofire'
end
validator = Installer::PodfileValidator.new(podfile)
validator.validate
validator.should.not.be.valid
validator.errors.should == ['The dependency `Alamofire` is not used in any concrete target.']
end
it 'errors when there are only abstract targets' do
podfile = Pod::Podfile.new do
abstract_target 'Abstract' do
pod 'Alamofire'
end
end
validator = Installer::PodfileValidator.new(podfile)
validator.validate
validator.should.not.be.valid
validator.errors.should == ['The dependency `Alamofire` is not used in any concrete target.']
end
it 'does not error when an abstract target has concrete children with complete inheritance' do
podfile = Pod::Podfile.new do
abstract_target 'Abstract' do
pod 'Alamofire'
target 'Concrete'
end
end
validator = Installer::PodfileValidator.new(podfile)
validator.validate
validator.should.be.valid
validator.errors.should.be.empty
end
it 'errors when an abstract target has concrete children with no inheritance' do
podfile = Pod::Podfile.new do
abstract_target 'Abstract' do
pod 'Alamofire'
target 'Concrete' do
inherit! :none
end
end
end
validator = Installer::PodfileValidator.new(podfile)
validator.validate
validator.should.not.be.valid
validator.errors.should == ['The dependency `Alamofire` is not used in any concrete target.']
end
it 'errors when an abstract target has concrete children with only search_paths inheritance' do
podfile = Pod::Podfile.new do
abstract_target 'Abstract' do
pod 'Alamofire'
target 'Concrete' do
inherit! :search_paths
end
end
end
validator = Installer::PodfileValidator.new(podfile)
validator.validate
validator.should.not.be.valid
validator.errors.should == ['The dependency `Alamofire` is not used in any concrete target.']
end
it 'does not error when an abstract target has multiple children with varied inheritance' do
podfile = Pod::Podfile.new do
abstract_target 'Abstract' do
pod 'Alamofire'
target 'Concrete' do
inherit! :none
end
target 'Other Concrete' do
end
end
end
validator = Installer::PodfileValidator.new(podfile)
validator.validate
validator.should.be.valid
validator.errors.should.be.empty
end
it 'does not error when an abstract target has multiple children with varied inheritance' do
podfile = Pod::Podfile.new do
abstract_target 'Abstract' do
pod 'Alamofire'
target 'Concrete' do
inherit! :search_paths
end
target 'Other Concrete' do
end
end
end
validator = Installer::PodfileValidator.new(podfile)
validator.validate
validator.should.be.valid
validator.errors.should.be.empty
end
end
end
end
......@@ -8,7 +8,6 @@ module Pod
Project.new(config.sandbox.project_path).save
@target = @project.targets.first
target_definition = Podfile::TargetDefinition.new('Pods', nil)
target_definition.link_with_first_target = true
@pod_bundle = AggregateTarget.new(target_definition, config.sandbox)
@pod_bundle.user_project = @project
@pod_bundle.client_root = project_path.dirname
......@@ -108,6 +107,18 @@ module Pod
it 'handles when xcconfig is set to another sandbox xcconfig' do
group = @project.new_group('Pods')
old_config = group.new_file('../Pods/Target Support Files/Pods-Foo/SampleConfig.xcconfig')
@target.build_configurations.each do |config|
config.base_configuration_reference = old_config
end
XCConfigIntegrator.integrate(@pod_bundle, [@target])
@target.build_configurations.each do |config|
config.base_configuration_reference.should.not == old_config
config.base_configuration_reference.path.should == @pod_bundle.xcconfig_relative_path(config.name)
end
@pod_bundle.stubs(:label).returns('Pods-Foo')
old_config = group.new_file('../Pods/Target Support Files/Pods/SampleConfig.xcconfig')
@target.build_configurations.each do |config|
config.base_configuration_reference = old_config
......
......@@ -13,7 +13,6 @@ module Pod
Project.new(config.sandbox.project_path).save
@target = @project.targets.first
target_definition = Podfile::TargetDefinition.new('Pods', nil)
target_definition.link_with_first_target = true
@pod_bundle = AggregateTarget.new(target_definition, config.sandbox)
@pod_bundle.user_project = @project
@pod_bundle.client_root = project_path.dirname
......
......@@ -9,18 +9,23 @@ module Pod
@podfile = Podfile.new do
platform :ios
xcodeproj sample_project_path
target 'SampleProject' do
pod 'JSONKit'
target :empty do
end
end
end
config.sandbox.project = Project.new(config.sandbox.project_path)
config.sandbox.project.save
@target = AggregateTarget.new(@podfile.target_definitions['Pods'], config.sandbox)
@target = AggregateTarget.new(@podfile.target_definitions['SampleProject'], config.sandbox)
@target.client_root = sample_project_path.dirname
@target.user_project = Xcodeproj::Project.open(@sample_project_path)
@target.user_target_uuids = ['A346496C14F9BE9A0080D870']
empty_library = AggregateTarget.new(@podfile.target_definitions[:empty], config.sandbox)
@integrator = UserProjectIntegrator.new(@podfile, config.sandbox, temporary_directory, [@target, empty_library])
@empty_library = AggregateTarget.new(@podfile.target_definitions[:empty], config.sandbox)
@empty_library.client_root = sample_project_path.dirname
@empty_library.user_project = @target.user_project
@empty_library.user_target_uuids = ['C0C495321B9E5C47004F9854']
@integrator = UserProjectIntegrator.new(@podfile, config.sandbox, temporary_directory, [@target, @empty_library])
end
#-----------------------------------------------------------------------#
......@@ -42,14 +47,8 @@ module Pod
end
it 'integrates the user targets' do
UserProjectIntegrator::TargetIntegrator.any_instance.expects(:integrate!)
@integrator.integrate!
end
it 'warns if the podfile does not contain any dependency' do
Podfile::TargetDefinition.any_instance.stubs(:empty?).returns(true)
UserProjectIntegrator::TargetIntegrator.any_instance.expects(:integrate!).twice
@integrator.integrate!
UI.warnings.should.include?('The Podfile does not contain any dependencies')
end
it 'deintegrates targets that are not associated with the podfile' do
......@@ -57,7 +56,7 @@ module Pod
Deintegrator.any_instance.expects(:deintegrate_target).with additional_project.new_target(:application, 'Other App', :ios)
user_project = @target.user_project
user_project.native_targets.each do |target|
next if target.name == 'SampleProject'
next if %w(SampleProject SampleProjectTests).include?(target.name)
Deintegrator.any_instance.expects(:deintegrate_target).with(target)
end
@integrator.stubs(:user_projects).returns([additional_project, user_project])
......@@ -201,9 +200,15 @@ module Pod
@integrator.send(:user_project_paths).should == [@sample_project_path]
end
it 'skips libraries with empty target definitions' do
@integrator.targets.map(&:name).should == ['Pods', 'Pods-empty']
@integrator.send(:targets_to_integrate).map(&:name).should == ['Pods']
it 'does not skip libraries with empty target definitions' do
@integrator.targets.map(&:name).should == ['Pods-SampleProject', 'Pods-SampleProject-empty']
@integrator.send(:targets_to_integrate).map(&:name).should == ['Pods-SampleProject', 'Pods-SampleProject-empty']
end
it 'does skip libraries with only abstract target definitions' do
@integrator.targets.map(&:name).should == ['Pods-SampleProject', 'Pods-SampleProject-empty']
@podfile.target_definition_list.each { |td| td.abstract = true }
@integrator.send(:targets_to_integrate).map(&:name).should == []
end
it 'skips saving projects that are not dirtied (but touches them instead)' do
......
......@@ -19,7 +19,12 @@ def generate_podfile(pods = ['JSONKit'])
Pod::Podfile.new do
platform :ios
xcodeproj SpecHelper.fixture('SampleProject/SampleProject'), 'Test' => :debug, 'App Store' => :release
target 'SampleProject' do
pods.each { |name| pod name }
target 'SampleProjectTests' do
inherit! :search_paths
end
end
end
end
......@@ -29,7 +34,12 @@ def generate_local_podfile
Pod::Podfile.new do
platform :ios
xcodeproj SpecHelper.fixture('SampleProject/SampleProject'), 'Test' => :debug, 'App Store' => :release
target 'SampleProject' do
pod 'Reachability', :path => SpecHelper.fixture('integration/Reachability')
target 'SampleProjectTests' do
inherit! :search_paths
end
end
end
end
......@@ -41,8 +51,8 @@ module Pod
CocoaPodsStats::Sender.any_instance.stubs(:send)
podfile = generate_podfile
lockfile = generate_lockfile
config.integrate_targets = false
@installer = Installer.new(config.sandbox, podfile, lockfile)
@installer.installation_options.integrate_targets = false
end
#-------------------------------------------------------------------------#
......@@ -140,13 +150,13 @@ module Pod
end
it 'integrates the user targets if the corresponding config is set' do
config.integrate_targets = true
@installer.installation_options.integrate_targets = true
@installer.expects(:integrate_user_project)
@installer.install!
end
it "doesn't integrates the user targets if the corresponding config is not set" do
config.integrate_targets = false
@installer.installation_options.integrate_targets = false
@installer.expects(:integrate_user_project).never
@installer.install!
end
......@@ -226,14 +236,16 @@ module Pod
pod 'OrangeFramework', :path => (fixture_path + 'orange-framework').to_s
pod 'monkey', :path => (fixture_path + 'monkey').to_s
target 'TestRunner', :exclusive => true do
target 'SampleProject'
target 'TestRunner' do
inherit! :search_paths
pod 'monkey', :path => (fixture_path + 'monkey').to_s
end
end
lockfile = generate_lockfile
config.integrate_targets = false
@installer = Installer.new(config.sandbox, podfile, lockfile)
@installer.installation_options.integrate_targets = false
@installer.install!
target = @installer.aggregate_targets.first
......@@ -262,11 +274,12 @@ module Pod
pod 'BananaLib', :path => (fixture_path + 'banana-lib').to_s
pod 'OrangeFramework', :path => (fixture_path + 'orange-framework').to_s
pod 'monkey', :path => (fixture_path + 'monkey').to_s
target 'SampleProject'
end
lockfile = generate_lockfile
config.integrate_targets = false
@installer = Installer.new(config.sandbox, podfile, lockfile)
@installer.installation_options.integrate_targets = false
should.raise(Informative) { @installer.install! }.message.should.match /conflict.*monkey/
end
......@@ -281,11 +294,12 @@ module Pod
use_frameworks!
pod 'BananaLib', :path => (fixture_path + 'banana-lib').to_s
pod 'monkey', :path => (fixture_path + 'monkey').to_s
target 'SampleProject'
end
lockfile = generate_lockfile
config.integrate_targets = false
@installer = Installer.new(config.sandbox, podfile, lockfile)
@installer.installation_options.integrate_targets = false
should.not.raise(Informative) { @installer.install! }
end
end
......@@ -296,14 +310,15 @@ module Pod
before do
fixture_path = ROOT + 'spec/fixtures'
config.repos_dir = fixture_path + 'spec-repos'
config.integrate_targets = false
@podfile = Pod::Podfile.new do
install! 'cocoapods', 'integrate_targets' => false
platform :ios, '8.0'
xcodeproj 'SampleProject/SampleProject'
use_frameworks!
pod 'BananaLib', :path => (fixture_path + 'banana-lib').to_s
pod 'OrangeFramework', :path => (fixture_path + 'orange-framework').to_s
pod 'monkey', :path => (fixture_path + 'monkey').to_s
target 'SampleProject'
end
@lockfile = generate_lockfile
......@@ -345,11 +360,12 @@ module Pod
platform :ios, '8.0'
xcodeproj 'SampleProject/SampleProject'
pod 'OrangeFramework', :path => (fixture_path + 'orange-framework').to_s
target 'SampleProject'
end
lockfile = generate_lockfile
config.integrate_targets = false
@installer = Installer.new(config.sandbox, podfile, lockfile)
@installer.installation_options.integrate_targets = false
should.raise(Informative) { @installer.install! }.message.should.match /use_frameworks/
end
end
......@@ -387,7 +403,7 @@ module Pod
it 'stores the targets created by the analyzer' do
@installer.send(:analyze)
@installer.aggregate_targets.map(&:name).sort.should == ['Pods']
@installer.aggregate_targets.map(&:name).sort.should == ['Pods-SampleProject', 'Pods-SampleProjectTests']
@installer.pod_targets.map(&:name).sort.should == ['JSONKit']
end
......@@ -395,7 +411,7 @@ module Pod
@installer.update = true
Installer::Analyzer.any_instance.expects(:update=).with(true)
@installer.send(:analyze)
@installer.aggregate_targets.map(&:name).sort.should == ['Pods']
@installer.aggregate_targets.map(&:name).sort.should == ['Pods-SampleProject', 'Pods-SampleProjectTests']
@installer.pod_targets.map(&:name).sort.should == ['JSONKit']
end
end
......@@ -453,24 +469,6 @@ module Pod
#-------------------------------------------------------------------------#
describe 'Downloading dependencies' do
it 'installs head pods' do
podfile = Podfile.new do
platform :osx, '10.10'
pod 'CargoBay', '2.1.0'
pod 'AFNetworking/NSURLSession', :head
end
@installer.stubs(:podfile).returns(podfile)
@installer.stubs(:lockfile).returns(nil)
Downloader::Git.any_instance.expects(:download).once
Downloader::Git.any_instance.expects(:download_head).once
Downloader::Git.any_instance.stubs(:checkout_options).returns({})
@installer.prepare
@installer.resolve_dependencies
@installer.send(:root_specs).sort_by(&:name).map(&:version).map(&:head?).should == [true, nil]
@installer.download_dependencies
UI.output.should.include 'HEAD based on 2.4.1'
end
describe '#install_pod_sources' do
it 'installs all the Pods which are marked as needing installation' do
spec = fixture_spec('banana-lib/BananaLib.podspec')
......@@ -527,7 +525,7 @@ module Pod
describe '#clean' do
it 'it cleans only if the config instructs to do it' do
config.clean = false
@installer.installation_options.clean = false
@installer.send(:clean_pod_sources)
Installer::PodSourceInstaller.any_instance.expects(:install!).never
end
......@@ -546,14 +544,14 @@ module Pod
end
it "creates build configurations for all of the user's targets" do
config.integrate_targets = true
@installer.installation_options.integrate_targets = true
@installer.send(:analyze)
@installer.send(:prepare_pods_project)
@installer.pods_project.build_configurations.map(&:name).sort.should == ['App Store', 'Debug', 'Release', 'Test']
end
it 'sets STRIP_INSTALLED_PRODUCT to NO for all configurations for the whole project' do
config.integrate_targets = true
@installer.installation_options.integrate_targets = true
@installer.send(:analyze)
@installer.send(:prepare_pods_project)
@installer.pods_project.build_settings('Debug')['STRIP_INSTALLED_PRODUCT'].should == 'NO'
......@@ -630,13 +628,13 @@ module Pod
@installer.send(:install_libraries)
end
it 'skips empty pod targets' do
it 'does not skip empty pod targets' do
spec = fixture_spec('banana-lib/BananaLib.podspec')
target_definition = Podfile::TargetDefinition.new(:default, nil)
pod_target = PodTarget.new([spec], [target_definition], config.sandbox)
@installer.stubs(:aggregate_targets).returns([])
@installer.stubs(:pod_targets).returns([pod_target])
Installer::PodTargetInstaller.any_instance.expects(:install!).never
Installer::PodTargetInstaller.any_instance.expects(:install!).once
@installer.send(:install_libraries)
end
......@@ -908,8 +906,8 @@ module Pod
podfile = Pod::Podfile.new do
platform :ios
end
config.integrate_targets = false
@installer = Installer.new(config.sandbox, podfile)
@installer.installation_options.integrate_targets = false
end
it 'runs the pre install hooks' do
......
......@@ -5,7 +5,6 @@ module Pod
describe 'In general' do
before do
@target_definition = Podfile::TargetDefinition.new('Pods', nil)
@target_definition.link_with_first_target = true
@lib = AggregateTarget.new(@target_definition, config.sandbox)
end
......@@ -29,7 +28,6 @@ module Pod
describe 'Support files' do
before do
@target_definition = Podfile::TargetDefinition.new('Pods', nil)
@target_definition.link_with_first_target = true
@lib = AggregateTarget.new(@target_definition, config.sandbox)
@lib.client_root = config.sandbox.root.dirname
end
......
......@@ -326,50 +326,6 @@ module Pod
]
end
it 'allows pre-release spec versions when a requirement has a ' \
'HEAD source' do
@podfile = Podfile.new do
platform :ios
pod 'MainSpec', :head
end
spec = Spec.new do |s|
s.name = 'MainSpec'
s.version = '1.2.3-pre'
s.platform = :ios
end
resolver = Resolver.new(config.sandbox, @podfile, empty_graph, SourcesManager.all)
resolver.expects(:find_cached_set).returns(Specification::Set::Head.new(spec))
specs = resolver.resolve.values.flatten.map(&:to_s).sort
specs.should == [
'MainSpec (HEAD based on 1.2.3-pre)',
]
end
it "marks a specification's version to be a HEAD version" do
podfile = Podfile.new do
platform :ios
pod 'FileMD5Hash'
pod 'JSONKit', :head
end
resolver = Resolver.new(config.sandbox, podfile, empty_graph, SourcesManager.all)
filemd5hash, jsonkit = resolver.resolve.values.first.sort_by(&:name)
filemd5hash.version.should.not.be.head
jsonkit.version.should.be.head
config.sandbox.head_pod?('FileMD5Hash').should.be.false
config.sandbox.head_pod?('JSONKit').should.be.true
end
it 'raises when unable to find a base spec for a HEAD dependency' do
podfile = Podfile.new do
platform :ios, '7.0'
pod 'ALEKit', :head
end
resolver = Resolver.new(config.sandbox, podfile, empty_graph, SourcesManager.all)
Source::Aggregate.any_instance.stubs(:search).with(Dependency.new('ALEKit', :head)).returns(nil)
e = should.raise(Informative) { resolver.resolve.values.flatten.map(&:to_s) }
e.message.should.match /Unable to find a specification for `ALEKit \(HEAD\)`/
end
it 'raises if it finds two conflicting explicit dependencies' do
podfile = Podfile.new do
platform :ios
......
......@@ -156,20 +156,6 @@ module Pod
#--------------------------------------#
it 'stores the list of the names of the pre-downloaded pods' do
@sandbox.store_head_pod('BananaLib')
@sandbox.head_pods.should == ['BananaLib']
end
it 'returns whether a Pod has been pre-downloaded' do
@sandbox.head_pods << 'BananaLib'
@sandbox.head_pod?('BananaLib').should.be.true
@sandbox.head_pod?('BananaLib/Subspec').should.be.true
@sandbox.head_pod?('Monkey').should.be.false
end
#--------------------------------------#
it 'returns the checkout sources of the Pods' do
@sandbox.store_pre_downloaded_pod('BananaLib/Subspec')
@sandbox.predownloaded_pods.should == ['BananaLib']
......
......@@ -5,7 +5,6 @@ module Pod
describe 'In general' do
before do
@target_definition = Podfile::TargetDefinition.new('Pods', nil)
@target_definition.link_with_first_target = true
@target = AggregateTarget.new(@target_definition, config.sandbox)
end
......@@ -42,7 +41,6 @@ module Pod
describe 'Support files' do
before do
@target_definition = Podfile::TargetDefinition.new('Pods', nil)
@target_definition.link_with_first_target = true
@target = AggregateTarget.new(@target_definition, config.sandbox)
@target.client_root = config.sandbox.root.dirname
end
......
......@@ -321,7 +321,7 @@ module Pod
validator.stubs(:validate_url)
validator.stubs(:validate_screenshots)
podfile = validator.send(:podfile_from_spec, :ios, '5.0')
dependency = podfile.target_definitions['Pods'].dependencies.first
dependency = podfile.target_definitions['App'].dependencies.first
dependency.external_source.key?(:podspec).should.be.true
end
......@@ -358,7 +358,7 @@ module Pod
it 'configures the deployment target' do
podfile = @validator.send(:podfile_from_spec, :ios, '5.0')
target_definition = podfile.target_definitions['Pods']
target_definition = podfile.target_definitions['App']
platform = target_definition.platform
platform.symbolic_name.should == :ios
platform.deployment_target.to_s.should == '5.0'
......@@ -366,13 +366,13 @@ module Pod
it 'includes the use_frameworks! directive' do
podfile = @validator.send(:podfile_from_spec, :ios, '5.0', true)
target_definition = podfile.target_definitions['Pods']
target_definition = podfile.target_definitions['App']
target_definition.uses_frameworks?.should == true
end
it 'includes the use_frameworks!(false) directive' do
podfile = @validator.send(:podfile_from_spec, :ios, '5.0', false)
target_definition = podfile.target_definitions['Pods']
target_definition = podfile.target_definitions['App']
# rubocop:disable Style/DoubleNegation
(!!target_definition.uses_frameworks?).should == false
# rubocop:enable Style/DoubleNegation
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment