Commit 298c6280 authored by Samuel E. Giddins's avatar Samuel E. Giddins

Merge pull request #4380 from CocoaPods/seg-open-project-once

Only open the user project once per installation
parents 8e142b2e d0081ee0
...@@ -6,6 +6,13 @@ To install release candidates run `[sudo] gem install cocoapods --pre` ...@@ -6,6 +6,13 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
## Master ## Master
##### Enhancements
* Reduce the number of times the user's Xcode project is opened, speeding up
installation.
[Samuel Giddins](https://github.com/segiddins)
[#4374](https://github.com/CocoaPods/CocoaPods/issues/4374)
##### Bug Fixes ##### Bug Fixes
* Fix a crash in dependency resolution when running Ruby 2.3. * Fix a crash in dependency resolution when running Ruby 2.3.
......
...@@ -548,9 +548,7 @@ module Pod ...@@ -548,9 +548,7 @@ module Pod
# #
def prepare_pods_project def prepare_pods_project
UI.message '- Creating Pods project' do UI.message '- Creating Pods project' do
object_version = aggregate_targets.map(&:user_project_path).compact.map do |path| object_version = aggregate_targets.map(&:user_project).compact.map { |p| p.object_version.to_i }.min
Xcodeproj::Project.open(path).object_version.to_i
end.min
if object_version if object_version
@pods_project = Pod::Project.new(sandbox.project_path, false, object_version) @pods_project = Pod::Project.new(sandbox.project_path, false, object_version)
......
...@@ -246,7 +246,7 @@ module Pod ...@@ -246,7 +246,7 @@ module Pod
if config.integrate_targets? if config.integrate_targets?
target_inspection = result.target_inspections[target_definition] target_inspection = result.target_inspections[target_definition]
target.user_project_path = target_inspection.project_path target.user_project = target_inspection.project
target.client_root = target.user_project_path.dirname target.client_root = target.user_project_path.dirname
target.user_target_uuids = target_inspection.project_target_uuids target.user_target_uuids = target_inspection.project_target_uuids
target.user_build_configurations = target_inspection.build_configurations target.user_build_configurations = target_inspection.build_configurations
...@@ -654,14 +654,21 @@ module Pod ...@@ -654,14 +654,21 @@ module Pod
def inspect_targets_to_integrate def inspect_targets_to_integrate
inspection_result = {} inspection_result = {}
UI.section 'Inspecting targets to integrate' do UI.section 'Inspecting targets to integrate' do
podfile.target_definition_list.each do |target_definition| inspectors = podfile.target_definition_list.map do |target_definition|
inspector = TargetInspector.new(target_definition, config.installation_root) TargetInspector.new(target_definition, config.installation_root)
end
inspectors.group_by(&:compute_project_path).each do |project_path, target_inspectors|
project = Xcodeproj::Project.open(project_path)
target_inspectors.each do |inspector|
target_definition = inspector.target_definition
inspector.user_project = project
results = inspector.compute_results results = inspector.compute_results
inspection_result[target_definition] = results inspection_result[target_definition] = results
UI.message('Using `ARCHS` setting to build architectures of ' \ UI.message('Using `ARCHS` setting to build architectures of ' \
"target `#{target_definition.label}`: (`#{results.archs.join('`, `')}`)") "target `#{target_definition.label}`: (`#{results.archs.join('`, `')}`)")
end end
end end
end
inspection_result inspection_result
end end
end end
......
...@@ -35,6 +35,10 @@ module Pod ...@@ -35,6 +35,10 @@ module Pod
# due to the presence of Swift source in the user's targets # due to the presence of Swift source in the user's targets
# #
attr_accessor :recommends_frameworks attr_accessor :recommends_frameworks
# @return [Xcodeproj::Project] the user's Xcode project
#
attr_accessor :project
end end
end end
end end
......
...@@ -25,27 +25,26 @@ module Pod ...@@ -25,27 +25,26 @@ module Pod
# Inspect the #target_definition # Inspect the #target_definition
# #
# @raise If no `user_project` is set
#
# @return [TargetInspectionResult] # @return [TargetInspectionResult]
# #
def compute_results def compute_results
project_path = compute_project_path raise ArgumentError, 'Cannot compute results without a user project set' unless user_project
user_project = Xcodeproj::Project.open(project_path)
targets = compute_targets(user_project) targets = compute_targets(user_project)
result = TargetInspectionResult.new result = TargetInspectionResult.new
result.target_definition = target_definition result.target_definition = target_definition
result.project_path = project_path result.project_path = user_project.path
result.project_target_uuids = targets.map(&:uuid) result.project_target_uuids = targets.map(&:uuid)
result.build_configurations = compute_build_configurations(targets) result.build_configurations = compute_build_configurations(targets)
result.platform = compute_platform(targets) result.platform = compute_platform(targets)
result.archs = compute_archs(targets) result.archs = compute_archs(targets)
result.project = user_project
result result
end end
#-----------------------------------------------------------------------#
private
# Returns the path of the user project that the #target_definition # Returns the path of the user project that the #target_definition
# should integrate. # should integrate.
# #
...@@ -77,6 +76,15 @@ module Pod ...@@ -77,6 +76,15 @@ module Pod
path path
end end
# @return [Xcodeproj::Project] the user's Xcode project, used for target
# inspection
#
attr_accessor :user_project
#-----------------------------------------------------------------------#
private
# Returns a list of the targets from the project of #target_definition # Returns a list of the targets from the project of #target_definition
# that needs to be integrated. # that needs to be integrated.
# #
......
...@@ -8,6 +8,10 @@ module Pod ...@@ -8,6 +8,10 @@ module Pod
# #
attr_accessor :sandbox_root attr_accessor :sandbox_root
# @return [Project] The Pods Xcode project.
#
attr_accessor :pods_project
# @return [Array<UmbrellaTargetDescription>] The list of # @return [Array<UmbrellaTargetDescription>] The list of
# the CocoaPods umbrella targets generated by the installer. # the CocoaPods umbrella targets generated by the installer.
# #
...@@ -29,7 +33,7 @@ module Pod ...@@ -29,7 +33,7 @@ module Pod
umbrella_targets_descriptions = [] umbrella_targets_descriptions = []
aggregate_targets.each do |umbrella| aggregate_targets.each do |umbrella|
desc = UmbrellaTargetDescription.new desc = UmbrellaTargetDescription.new
desc.user_project_path = umbrella.user_project_path desc.user_project = umbrella.user_project
desc.user_target_uuids = umbrella.user_target_uuids desc.user_target_uuids = umbrella.user_target_uuids
desc.specs = umbrella.specs desc.specs = umbrella.specs
desc.platform_name = umbrella.platform.name desc.platform_name = umbrella.platform.name
...@@ -40,6 +44,7 @@ module Pod ...@@ -40,6 +44,7 @@ module Pod
result = new result = new
result.sandbox_root = sandbox.root.to_s result.sandbox_root = sandbox.root.to_s
result.pods_project = sandbox.project
result.umbrella_targets = umbrella_targets_descriptions result.umbrella_targets = umbrella_targets_descriptions
result result
end end
...@@ -47,10 +52,17 @@ module Pod ...@@ -47,10 +52,17 @@ module Pod
# Pure data class which describes and umbrella target. # Pure data class which describes and umbrella target.
# #
class UmbrellaTargetDescription class UmbrellaTargetDescription
# @return [Xcodeproj::Project] The user project into which this target
# is integrated.
#
attr_accessor :user_project
# @return [String] The path of the user project # @return [String] The path of the user project
# integrated by this target. # integrated by this target.
# #
attr_accessor :user_project_path def user_project_path
user_project.path if user_project
end
# @return [Array<String>] The list of the UUIDs of the # @return [Array<String>] The list of the UUIDs of the
# user targets integrated by this umbrella # user targets integrated by this umbrella
......
...@@ -268,7 +268,7 @@ module Pod ...@@ -268,7 +268,7 @@ module Pod
# match the given target. # match the given target.
# #
def native_targets def native_targets
@native_targets ||= target.user_targets(user_project) @native_targets ||= target.user_targets
end end
# @return [Array<PBXNativeTarget>] The list of all the targets that # @return [Array<PBXNativeTarget>] The list of all the targets that
...@@ -305,7 +305,7 @@ module Pod ...@@ -305,7 +305,7 @@ module Pod
# @return [Project] # @return [Project]
# #
def user_project def user_project
@user_project ||= Xcodeproj::Project.open(target.user_project_path) target.user_project
end end
# @return [Specification::Consumer] the consumer for the specifications. # @return [Specification::Consumer] the consumer for the specifications.
......
...@@ -54,13 +54,17 @@ module Pod ...@@ -54,13 +54,17 @@ module Pod
# #
attr_accessor :client_root attr_accessor :client_root
# @return [Pathname] the path of the user project that this target will # @return [Xcodeproj::Project] the user project that this target will
# integrate as identified by the analyzer. # integrate as identified by the analyzer.
# #
# @note The project instance is not stored to prevent editing different attr_accessor :user_project
# instances.
# @return [Pathname] the path of the user project that this target will
# integrate as identified by the analyzer.
# #
attr_accessor :user_project_path def user_project_path
user_project.path if user_project
end
# @return [Array<String>] the list of the UUIDs of the user targets that # @return [Array<String>] the list of the UUIDs of the user targets that
# will be integrated by this target as identified by the analyzer. # will be integrated by this target as identified by the analyzer.
...@@ -72,16 +76,12 @@ module Pod ...@@ -72,16 +76,12 @@ module Pod
# List all user targets that will be integrated by this #target. # List all user targets that will be integrated by this #target.
# #
# @param [Xcodeproj::Project] project
# The project to search for the user targets
#
# @return [Array<PBXNativeTarget>] # @return [Array<PBXNativeTarget>]
# #
def user_targets(project = nil) def user_targets
return [] unless user_project_path return [] unless user_project
project ||= Xcodeproj::Project.open(user_project_path)
user_target_uuids.map do |uuid| user_target_uuids.map do |uuid|
native_target = project.objects_by_uuid[uuid] native_target = user_project.objects_by_uuid[uuid]
unless native_target unless native_target
raise Informative, '[Bug] Unable to find the target with ' \ raise Informative, '[Bug] Unable to find the target with ' \
"the `#{uuid}` UUID for the `#{self}` integration library" "the `#{uuid}` UUID for the `#{self}` integration library"
......
...@@ -3,13 +3,15 @@ require File.expand_path('../../../spec_helper', __FILE__) ...@@ -3,13 +3,15 @@ require File.expand_path('../../../spec_helper', __FILE__)
module Pod module Pod
describe Installer::PostInstallHooksContext do describe Installer::PostInstallHooksContext do
it 'offers a convenience method to be generated' do it 'offers a convenience method to be generated' do
sandbox = stub(:root => '/path') pods_project = Project.new('/path/Pods.xcodeproj')
sandbox = stub(:root => '/path', :project => pods_project)
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
user_project = Xcodeproj::Project.open(SpecHelper.create_sample_app_copy_from_fixture('SampleProject'))
target_definition = Podfile::TargetDefinition.new('Pods', nil) target_definition = Podfile::TargetDefinition.new('Pods', nil)
pod_target = PodTarget.new([spec], [target_definition], config.sandbox) pod_target = PodTarget.new([spec], [target_definition], config.sandbox)
umbrella = AggregateTarget.new(target_definition, config.sandbox) umbrella = AggregateTarget.new(target_definition, config.sandbox)
umbrella.user_project_path = '/path/project.xcodeproj' umbrella.user_project = user_project
umbrella.user_target_uuids = ['UUID'] umbrella.user_target_uuids = ['UUID']
umbrella.stubs(:platform).returns(Platform.new(:ios, '8.0')) umbrella.stubs(:platform).returns(Platform.new(:ios, '8.0'))
umbrella.pod_targets = [pod_target] umbrella.pod_targets = [pod_target]
...@@ -17,10 +19,11 @@ module Pod ...@@ -17,10 +19,11 @@ module Pod
result = Installer::PostInstallHooksContext.generate(sandbox, [umbrella]) result = Installer::PostInstallHooksContext.generate(sandbox, [umbrella])
result.class.should == Installer::PostInstallHooksContext result.class.should == Installer::PostInstallHooksContext
result.sandbox_root.should == '/path' result.sandbox_root.should == '/path'
result.pods_project.should == pods_project
result.umbrella_targets.count.should == 1 result.umbrella_targets.count.should == 1
umbrella_target = result.umbrella_targets.first umbrella_target = result.umbrella_targets.first
umbrella_target.user_target_uuids.should == ['UUID'] umbrella_target.user_target_uuids.should == ['UUID']
umbrella_target.user_project_path.should == '/path/project.xcodeproj' umbrella_target.user_project.should == user_project
umbrella_target.specs.should == [spec] umbrella_target.specs.should == [spec]
umbrella_target.platform_name.should == :ios umbrella_target.platform_name.should == :ios
umbrella_target.platform_deployment_target.should == '8.0' umbrella_target.platform_deployment_target.should == '8.0'
......
...@@ -24,7 +24,6 @@ module Pod ...@@ -24,7 +24,6 @@ module Pod
@target = AggregateTarget.new(@target_definition, config.sandbox) @target = AggregateTarget.new(@target_definition, config.sandbox)
@target.stubs(:platform).returns(Platform.new(:ios, '6.0')) @target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@target.user_project_path = config.sandbox.root + '../user_project.xcodeproj'
@target.client_root = config.sandbox.root.dirname @target.client_root = config.sandbox.root.dirname
@target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug } @target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug }
......
...@@ -10,7 +10,7 @@ module Pod ...@@ -10,7 +10,7 @@ module Pod
target_definition = Podfile::TargetDefinition.new('Pods', nil) target_definition = Podfile::TargetDefinition.new('Pods', nil)
target_definition.link_with_first_target = true target_definition.link_with_first_target = true
@pod_bundle = AggregateTarget.new(target_definition, config.sandbox) @pod_bundle = AggregateTarget.new(target_definition, config.sandbox)
@pod_bundle.user_project_path = project_path @pod_bundle.user_project = @project
@pod_bundle.client_root = project_path.dirname @pod_bundle.client_root = project_path.dirname
@pod_bundle.user_target_uuids = [@target.uuid] @pod_bundle.user_target_uuids = [@target.uuid]
configuration = Xcodeproj::Config.new( configuration = Xcodeproj::Config.new(
......
...@@ -10,12 +10,12 @@ module Pod ...@@ -10,12 +10,12 @@ module Pod
before do before do
project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject') project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
@project = Xcodeproj::Project.open(project_path) @project = Xcodeproj::Project.open(project_path)
Xcodeproj::Project.new(config.sandbox.project_path).save Project.new(config.sandbox.project_path).save
@target = @project.targets.first @target = @project.targets.first
target_definition = Podfile::TargetDefinition.new('Pods', nil) target_definition = Podfile::TargetDefinition.new('Pods', nil)
target_definition.link_with_first_target = true target_definition.link_with_first_target = true
@pod_bundle = AggregateTarget.new(target_definition, config.sandbox) @pod_bundle = AggregateTarget.new(target_definition, config.sandbox)
@pod_bundle.user_project_path = project_path @pod_bundle.user_project = @project
@pod_bundle.client_root = project_path.dirname @pod_bundle.client_root = project_path.dirname
@pod_bundle.user_target_uuids = [@target.uuid] @pod_bundle.user_target_uuids = [@target.uuid]
configuration = Xcodeproj::Config.new( configuration = Xcodeproj::Config.new(
......
...@@ -17,7 +17,7 @@ module Pod ...@@ -17,7 +17,7 @@ module Pod
Xcodeproj::Project.new(config.sandbox.project_path).save Xcodeproj::Project.new(config.sandbox.project_path).save
@target = AggregateTarget.new(@podfile.target_definitions['Pods'], config.sandbox) @target = AggregateTarget.new(@podfile.target_definitions['Pods'], config.sandbox)
@target.client_root = sample_project_path.dirname @target.client_root = sample_project_path.dirname
@target.user_project_path = sample_project_path @target.user_project = Xcodeproj::Project.open(@sample_project_path)
@target.user_target_uuids = ['A346496C14F9BE9A0080D870'] @target.user_target_uuids = ['A346496C14F9BE9A0080D870']
empty_library = AggregateTarget.new(@podfile.target_definitions[:empty], config.sandbox) empty_library = AggregateTarget.new(@podfile.target_definitions[:empty], config.sandbox)
@integrator = UserProjectIntegrator.new(@podfile, config.sandbox, temporary_directory, [@target, empty_library]) @integrator = UserProjectIntegrator.new(@podfile, config.sandbox, temporary_directory, [@target, empty_library])
......
...@@ -491,7 +491,7 @@ module Pod ...@@ -491,7 +491,7 @@ module Pod
end end
before do before do
@installer.stubs(:analysis_result).returns(stub(:all_user_build_configurations => {})) @installer.stubs(:analysis_result).returns(stub(:all_user_build_configurations => {}, :target_inspections => nil))
end end
it 'creates the Pods project' do it 'creates the Pods project' do
...@@ -656,7 +656,7 @@ module Pod ...@@ -656,7 +656,7 @@ module Pod
describe '#write_pod_project' do describe '#write_pod_project' do
before do before do
@installer.stubs(:aggregate_targets).returns([]) @installer.stubs(:aggregate_targets).returns([])
@installer.stubs(:analysis_result).returns(stub(:all_user_build_configurations => {})) @installer.stubs(:analysis_result).returns(stub(:all_user_build_configurations => {}, :target_inspections => nil))
@installer.send(:prepare_pods_project) @installer.send(:prepare_pods_project)
end end
...@@ -695,7 +695,7 @@ module Pod ...@@ -695,7 +695,7 @@ module Pod
aggregate_target = AggregateTarget.new(nil, config.sandbox) aggregate_target = AggregateTarget.new(nil, config.sandbox)
aggregate_target.stubs(:platform).returns(Platform.new(:ios, '6.0')) aggregate_target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
aggregate_target.stubs(:user_project_path).returns(proj.path) aggregate_target.stubs(:user_project).returns(proj)
@installer.stubs(:aggregate_targets).returns([aggregate_target]) @installer.stubs(:aggregate_targets).returns([aggregate_target])
@installer.send(:prepare_pods_project) @installer.send(:prepare_pods_project)
......
...@@ -31,7 +31,7 @@ module Pod ...@@ -31,7 +31,7 @@ module Pod
it 'returns the user targets' do it 'returns the user targets' do
project_path = SpecHelper.fixture('SampleProject/SampleProject.xcodeproj') project_path = SpecHelper.fixture('SampleProject/SampleProject.xcodeproj')
@target.user_project_path = project_path @target.user_project = Xcodeproj::Project.open(project_path)
@target.user_target_uuids = ['A346496C14F9BE9A0080D870'] @target.user_target_uuids = ['A346496C14F9BE9A0080D870']
targets = @target.user_targets targets = @target.user_targets
targets.count.should == 1 targets.count.should == 1
......
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