Commit 8ea1f5da authored by Fabio Pelosin's avatar Fabio Pelosin

[Project] Overhaul

parent fb38487b
...@@ -17,7 +17,7 @@ GIT ...@@ -17,7 +17,7 @@ GIT
GIT GIT
remote: https://github.com/CocoaPods/Xcodeproj.git remote: https://github.com/CocoaPods/Xcodeproj.git
revision: 5f0fc07355716817b7591a859774a93f6773d559 revision: c7f6420dd3d0f1a5e3ab3f4983500d5076f85f28
branch: paths-refactor branch: paths-refactor
specs: specs:
xcodeproj (0.9.0) xcodeproj (0.9.0)
......
...@@ -285,13 +285,23 @@ module Pod ...@@ -285,13 +285,23 @@ module Pod
# #
def prepare_pods_project def prepare_pods_project
UI.message "- Creating Pods project" do UI.message "- Creating Pods project" do
@pods_project = Pod::Project.new(sandbox) @pods_project = Pod::Project.new(sandbox.project_path)
analysis_result.all_user_build_configurations.each do |name, type| analysis_result.all_user_build_configurations.each do |name, type|
@pods_project.add_build_configuration(name, type) @pods_project.add_build_configuration(name, type)
end end
pod_names = pod_targets.map(&:pod_name).uniq
pod_names.each do |pod_name|
path = sandbox.pod_dir(pod_name)
local = sandbox.local?(pod_name)
@pods_project.add_pod_group(pod_name, path, local)
end
if config.podfile_path if config.podfile_path
@pods_project.add_podfile(config.podfile_path) @pods_project.add_podfile(config.podfile_path)
end end
sandbox.project = @pods_project sandbox.project = @pods_project
platforms = aggregate_targets.map(&:platform) platforms = aggregate_targets.map(&:platform)
osx_deployment_target = platforms.select { |p| p.name == :osx }.map(&:deployment_target).min osx_deployment_target = platforms.select { |p| p.name == :osx }.map(&:deployment_target).min
...@@ -378,6 +388,8 @@ module Pod ...@@ -378,6 +388,8 @@ module Pod
# #
def write_pod_project def write_pod_project
UI.message "- Writing Xcode project file to #{UI.path sandbox.project_path}" do UI.message "- Writing Xcode project file to #{UI.path sandbox.project_path}" do
pods_project.pods.remove_from_project if pods_project.pods.empty?
pods_project.local_pods.remove_from_project if pods_project.local_pods.empty?
pods_project.main_group.sort_by_type! pods_project.main_group.sort_by_type!
pods_project['Frameworks'].sort_by_type! pods_project['Frameworks'].sort_by_type!
pods_project.save pods_project.save
......
...@@ -65,10 +65,6 @@ module Pod ...@@ -65,10 +65,6 @@ module Pod
# @note The source files are grouped by Pod and in turn by subspec # @note The source files are grouped by Pod and in turn by subspec
# (recursively). # (recursively).
# #
# @note Pods are generally added to the `Pods` group, however, if they
# have a local source they are added to the
# `Local Pods` group.
#
# @return [void] # @return [void]
# #
def add_source_files_references def add_source_files_references
......
...@@ -90,7 +90,7 @@ module Pod ...@@ -90,7 +90,7 @@ module Pod
path = library.copy_resources_script_path path = library.copy_resources_script_path
UI.message "- Generating copy resources script at #{UI.path(path)}" do UI.message "- Generating copy resources script at #{UI.path(path)}" do
file_accessors = library.pod_targets.map(&:file_accessors).flatten file_accessors = library.pod_targets.map(&:file_accessors).flatten
resource_paths = file_accessors.map { |accessor| accessor.resources.flatten.map { |res| res.relative_path_from(project.path) }}.flatten resource_paths = file_accessors.map { |accessor| accessor.resources.flatten.map { |res| res.relative_path_from(project.path.dirname) }}.flatten
resource_bundles = file_accessors.map { |accessor| accessor.resource_bundles.keys.map {|name| "${TARGET_BUILD_DIR}/#{name}.bundle" } }.flatten resource_bundles = file_accessors.map { |accessor| accessor.resource_bundles.keys.map {|name| "${TARGET_BUILD_DIR}/#{name}.bundle" } }.flatten
resources = [] resources = []
resources.concat(resource_paths) resources.concat(resource_paths)
......
...@@ -40,7 +40,7 @@ module Pod ...@@ -40,7 +40,7 @@ module Pod
consumer = file_accessor.spec_consumer consumer = file_accessor.spec_consumer
flags = compiler_flags_for_consumer(consumer) flags = compiler_flags_for_consumer(consumer)
source_files = file_accessor.source_files source_files = file_accessor.source_files
file_refs = source_files.map { |sf| project.file_reference(sf) } file_refs = source_files.map { |sf| project.reference_for_path(sf) }
target.add_file_references(file_refs, flags) target.add_file_references(file_refs, flags)
file_accessor.spec_consumer.frameworks.each do |framework| file_accessor.spec_consumer.frameworks.each do |framework|
...@@ -61,7 +61,7 @@ module Pod ...@@ -61,7 +61,7 @@ module Pod
UI.message "- Adding resource bundles to Pods project" do UI.message "- Adding resource bundles to Pods project" do
library.file_accessors.each do |file_accessor| library.file_accessors.each do |file_accessor|
file_accessor.resource_bundles.each do |bundle_name, paths| file_accessor.resource_bundles.each do |bundle_name, paths|
file_references = paths.map { |sf| project.file_reference(sf) } file_references = paths.map { |sf| project.reference_for_path(sf) }
group = project.group_for_spec(file_accessor.spec.name, :resources) group = project.group_for_spec(file_accessor.spec.name, :resources)
product_group = project.group_for_spec(file_accessor.spec.name, :resources) product_group = project.group_for_spec(file_accessor.spec.name, :resources)
bundle_target = project.new_resources_bundle(bundle_name, file_accessor.spec_consumer.platform_name, product_group) bundle_target = project.new_resources_bundle(bundle_name, file_accessor.spec_consumer.platform_name, product_group)
......
...@@ -9,75 +9,105 @@ module Pod ...@@ -9,75 +9,105 @@ module Pod
# #
class Project < Xcodeproj::Project class Project < Xcodeproj::Project
# @return [Sandbox] the sandbox which returns the information about which # @param [Pathname, String] path @see path
# Pods are local. # @param [Bool] skip_initialization
# Wether the project should be initialized from scratch.
# #
attr_reader :sandbox def initialize(path, skip_initialization = false)
super
# @param [Sandbox] sandbox @see #sandbox
#
def initialize(sandbox)
super(sandbox.project_path)
@sandbox = sandbox
@support_files_group = new_group('Targets Support Files') @support_files_group = new_group('Targets Support Files')
@refs_by_absolute_path = {} @refs_by_absolute_path = {}
@pods = new_group('Pods')
@local_pods = new_group('Local Pods')
end end
# @return [Pathname] the directory where the project is stored. # @return [PBXGroup] The group for the support files of the aggregate
# targets.
# #
def root attr_reader :support_files_group
@root ||= path.dirname
end
# @return [String] a string representation suited for debugging. # @return [PBXGroup] The group for the Pods.
# #
def inspect attr_reader :pods
"#<#{self.class}> path:#{path}"
end # @return [PBXGroup] The group for Local Pods.
#
attr_reader :local_pods
public public
# @!group Groups # @!group Pod Groups
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# @return [PBXGroup] the group where the support files for the Pod # Creates a new group for the Pod with the given name and configures its
# libraries should be added. # path.
# #
attr_reader :support_files_group # @param [String] pod_name
# The name of the Pod.
# Returns the `Pods` group, creating it if needed. #
# @param [#to_s] path
# The path to the root of the Pod.
# #
# @return [PBXGroup] the group. # @param [Bool] local
# Wether the group should be added to the Local Pods group.
# #
def pods # @param [Bool] absolute
@pods ||= new_group('Pods') # Wether the path of the group should be set as absolute.
#
# @return [PBXGroup] The new group.
#
def add_pod_group(pod_name, path, local = false, absolute = false)
raise "[BUG]" if pod_group(pod_name)
parent_group = local ? local_pods : pods
source_tree = absolute ? :absolute : :group
parent_group.new_group(pod_name, path, source_tree)
end
# @return [Array<PBXGroup>] Returns all the group of the Pods.
#
def pod_groups
pods.children.objects + local_pods.children.objects
end end
# Returns the `Local Pods` group, creating it if needed. This group is used # Returns the group for the Pod with the given name.
# to contain locally sourced pods. #
# @param [String] pod_name
# The name of the Pod.
# #
# @return [PBXGroup] the group. # @return [PBXGroup] The group.
# #
def local_pods def pod_group(pod_name)
@local_pods ||= new_group('Local Pods') pod_groups.find { |group| group.name == pod_name }
end end
# @return [PBXGroup] the group for the spec with the given name. # @return [Hash] The names of the specification subgroups by key.
# #
def group_for_spec(spec_name, type = nil) SPEC_SUBGROUPS = {
local = sandbox.local?(spec_name) :source_files => 'Source Files',
parent_group = local ? local_pods : pods :resources => 'Resources',
spec_group = add_spec_group(spec_name, parent_group) :frameworks_and_libraries => 'Frameworks & Libraries',
if type :support_files => 'Support Files',
case type }
when :source_files then sub_group = 'Source Files'
when :resources then sub_group = 'Resources' # Returns the group for the specification with the give name creating it if
when :frameworks_and_libraries then sub_group = 'Frameworks & Libraries' # needed.
when :support_files then sub_group = 'Support Files' #
else raise "[BUG]" # @param [String] spec_name
end # The full name of the specification.
spec_group.find_subpath(sub_group, true) #
# @param [Symbol] subgroup_key
# The optional key of the subgroup (@see #{SPEC_SUBGROUPS})
#
# @return [PBXGroup] The group.
#
def group_for_spec(spec_name, subgroup_key = nil)
spec_group = spec_group(spec_name)
if subgroup_key
subgroup = SPEC_SUBGROUPS[subgroup_key]
raise ArgumentError, "Unrecognized subgroup `#{subgroup_key}`" unless subgroup
spec_group.find_subpath(subgroup, true)
else else
spec_group spec_group
end end
...@@ -89,57 +119,54 @@ module Pod ...@@ -89,57 +119,54 @@ module Pod
# @!group File references # @!group File references
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# Adds a file reference for each one of the given files in the specified # Adds a file reference to given path as a child of the given group.
# group, namespaced by specification unless a file reference for the given
# path already exits.
#
# @note With this set-up different subspecs might not reference the same
# file (i.e. the first will win). Not sure thought if this is a
# limitation or a feature.
#
# @param [Array<Pathname,String>] paths
# The files for which the file reference is needed.
# #
# @param [String] spec_name # @param [Array<Pathname,String>] absolute_path
# The full name of the specification. # The path of the file.
# #
# @param [PBXGroup] parent_group # @param [PBXGroup] group
# The group where the file references should be added. # The group for the new file reference.
# #
# @return [void] # @return [PBXFileReference] The new file reference.
# #
def add_file_reference(absolute_path, group) def add_file_reference(absolute_path, group)
# existing = file_reference(absolute_paths) unless Pathname.new(absolute_path).absolute?
# unless existing raise ArgumentError, "Paths must be absolute #{absolute_path}"
absolute_path = Pathname.new(absolute_path) end
ref = group.new_file(absolute_path)
@refs_by_absolute_path[absolute_path] = ref if ref = reference_for_path(absolute_path)
# end ref
else
ref = group.new_file(absolute_path)
@refs_by_absolute_path[absolute_path.to_s] = ref
end
end end
# Returns the file reference for the given absolute file path. # Returns the file reference for the given absolute path.
# #
# @param [Pathname,String] absolute_path # @param [#to_s] absolute_path
# The absolute path of the file whose reference is needed. # The absolute path of the file whose reference is needed.
# #
# @return [PBXFileReference] The file reference. # @return [PBXFileReference] The file reference.
# @return [Nil] If no file reference could be found. # @return [Nil] If no file reference could be found.
# #
def file_reference(absolute_path) def reference_for_path(absolute_path)
absolute_path = Pathname.new(absolute_path) unless Pathname.new(absolute_path).absolute?
refs_by_absolute_path[absolute_path] raise ArgumentError, "Paths must be absolute #{absolute_path}"
end
refs_by_absolute_path[absolute_path.to_s]
end end
# Adds a file reference to the podfile. # Adds a file reference to the Podfile.
# #
# @param [Pathname,String] podfile_path # @param [#to_s] podfile_path
# The path of the Podfile. # The path of the Podfile.
# #
# @return [PBXFileReference] The file reference. # @return [PBXFileReference] The new file reference.
# #
def add_podfile(podfile_path) def add_podfile(podfile_path)
podfile_path = Pathname.new(podfile_path) podfile_ref = new_file(podfile_path, :project)
podfile_ref = new_file(podfile_path)
podfile_ref.xc_language_specification_identifier = 'xcode.lang.ruby' podfile_ref.xc_language_specification_identifier = 'xcode.lang.ruby'
podfile_ref.last_known_file_type = 'text' podfile_ref.last_known_file_type = 'text'
podfile_ref podfile_ref
...@@ -151,29 +178,27 @@ module Pod ...@@ -151,29 +178,27 @@ module Pod
# @!group Private helpers # @!group Private helpers
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# @return [Hash{Pathname => PBXFileReference}] The file references grouped # @return [Hash{String => PBXFileReference}] The file references grouped
# by absolute path. # by absolute path.
# #
attr_reader :refs_by_absolute_path attr_reader :refs_by_absolute_path
# Returns a subgroup of the give group for the given spec creating it if # Returns the group for the given specification creating it if needed.
# needed.
# #
# @param [String] spec_name # @param [String] spec_name
# The full name of the specification. # The full name of the specification.
# #
# @param [PBXGroup] root_group
# The group where to add the specification. Either `Pods` or `Local
# Pods`.
#
# @return [PBXGroup] The group for the spec with the given name. # @return [PBXGroup] The group for the spec with the given name.
# #
def add_spec_group(spec_name, root_group) def spec_group(spec_name)
current_group = root_group pod_name = Specification.root_name(spec_name)
group = nil group = pod_group(pod_name)
spec_name.split('/').each do |name| raise "[Bug] Unable to locate group for Pod named `#{pod_name}`" unless group
group = current_group[name] || current_group.new_group(name) if spec_name != pod_name
current_group = group subspecs_names = spec_name.gsub(pod_name + '/', '').split('/')
subspecs_names.each do |name|
group = group[name] || group.new_group(name)
end
end end
group group
end end
......
Subproject commit fa5c727b65b4499b39d981685f93fc6369f46489 Subproject commit bcc200c3fee14a7506e9c865fe3b6912a955aa94
...@@ -193,21 +193,26 @@ def yaml_should_match(expected, produced) ...@@ -193,21 +193,26 @@ def yaml_should_match(expected, produced)
produced_yaml.delete('COCOAPODS') produced_yaml.delete('COCOAPODS')
desc = [] desc = []
desc << "YAML comparison error `#{expected}`" desc << "YAML comparison error `#{expected}`"
diff_options = {:key_1 => "$produced", :key_2 => "$expected"}
diff = Xcodeproj::Differ.diff(produced_yaml, expected_yaml, diff_options).to_yaml desc << ("--- YAML DIFF " << "-" * 65)
diff.gsub!("$produced", "produced".green) diffy_diff = ''
diff.gsub!("$expected", "expected".red)
desc << ("--- DIFF " << "-" * 70)
Diffy::Diff.new(expected.to_s, produced.to_s, :source => 'files', :context => 3).each do |line| Diffy::Diff.new(expected.to_s, produced.to_s, :source => 'files', :context => 3).each do |line|
case line case line
when /^\+/ then desc << line.gsub("\n",'').green when /^\+/ then diffy_diff << line.green
when /^-/ then desc << line.gsub("\n",'').red when /^-/ then diffy_diff << line.red
else desc << line.gsub("\n",'') else diffy_diff << line
end end
end end
desc << ("--- DIFF " << "-" * 70) desc << diffy_diff
desc << ("--- XCODEPROJ DIFF " << "-" * 60)
diff_options = {:key_1 => "$produced", :key_2 => "$expected"}
diff = Xcodeproj::Differ.diff(produced_yaml, expected_yaml, diff_options).to_yaml
diff.gsub!("$produced", "produced".green)
diff.gsub!("$expected", "expected".red)
desc << diff desc << diff
desc << ("--- END " << "-" * 70) desc << ("--- END " << "-" * 70)
expected_yaml.should.satisfy(desc * "\n\n") do expected_yaml.should.satisfy(desc * "\n\n") do
if RUBY_VERSION < "1.9" if RUBY_VERSION < "1.9"
true # CP is not sorting array derived from hashes whose order is true # CP is not sorting array derived from hashes whose order is
......
...@@ -7,7 +7,8 @@ module Pod ...@@ -7,7 +7,8 @@ module Pod
@file_accessor = fixture_file_accessor('banana-lib/BananaLib.podspec') @file_accessor = fixture_file_accessor('banana-lib/BananaLib.podspec')
@pod_target = PodTarget.new([], nil, config.sandbox) @pod_target = PodTarget.new([], nil, config.sandbox)
@pod_target.file_accessors = [@file_accessor] @pod_target.file_accessors = [@file_accessor]
@project = Project.new(config.sandbox) @project = Project.new(config.sandbox.project_path)
@project.add_pod_group('BananaLib', fixture('banana-lib'))
@installer = Installer::FileReferencesInstaller.new(config.sandbox, [@pod_target], @project) @installer = Installer::FileReferencesInstaller.new(config.sandbox, [@pod_target], @project)
end end
...@@ -25,14 +26,7 @@ module Pod ...@@ -25,14 +26,7 @@ module Pod
@installer.install! @installer.install!
file_ref = @installer.pods_project['Pods/BananaLib/Source Files/Banana.m'] file_ref = @installer.pods_project['Pods/BananaLib/Source Files/Banana.m']
file_ref.should.be.not.nil file_ref.should.be.not.nil
file_ref.path.should == "../../spec/fixtures/banana-lib/Classes/Banana.m" file_ref.path.should == "Classes/Banana.m"
end
it "adds the files references of the local Pods in a dedicated group" do
config.sandbox.store_local_path('BananaLib', 'Some Path')
@installer.install!
file_ref = @installer.pods_project['Local Pods/BananaLib/Source Files/Banana.m']
file_ref.should.be.not.nil
end end
xit "adds the file references of the frameworks of the projet" do xit "adds the file references of the frameworks of the projet" do
...@@ -47,7 +41,7 @@ module Pod ...@@ -47,7 +41,7 @@ module Pod
@installer.install! @installer.install!
file_ref = @installer.pods_project['Pods/BananaLib/Resources/logo-sidebar.png'] file_ref = @installer.pods_project['Pods/BananaLib/Resources/logo-sidebar.png']
file_ref.should.be.not.nil file_ref.should.be.not.nil
file_ref.path.should == "../../spec/fixtures/banana-lib/Resources/logo-sidebar.png" file_ref.path.should == "Resources/logo-sidebar.png"
end end
it "links the build headers" do it "links the build headers" do
......
...@@ -9,12 +9,13 @@ module Pod ...@@ -9,12 +9,13 @@ module Pod
xcodeproj 'dummy' xcodeproj 'dummy'
end end
@target_definition = @podfile.target_definitions['Pods'] @target_definition = @podfile.target_definitions['Pods']
@project = Project.new(config.sandbox) @project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project config.sandbox.project = @project
path_list = Sandbox::PathList.new(fixture('banana-lib')) path_list = Sandbox::PathList.new(fixture('banana-lib'))
@spec = fixture_spec('banana-lib/BananaLib.podspec') @spec = fixture_spec('banana-lib/BananaLib.podspec')
file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios)) file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios))
@project.add_pod_group('BananaLib', fixture('banana-lib'))
group = @project.group_for_spec('BananaLib', :source_files) group = @project.group_for_spec('BananaLib', :source_files)
file_accessor.source_files.each do |file| file_accessor.source_files.each do |file|
@project.add_file_reference(file, group) @project.add_file_reference(file, group)
......
...@@ -9,12 +9,13 @@ module Pod ...@@ -9,12 +9,13 @@ module Pod
xcodeproj 'dummy' xcodeproj 'dummy'
end end
@target_definition = @podfile.target_definitions['Pods'] @target_definition = @podfile.target_definitions['Pods']
@project = Project.new(config.sandbox) @project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project config.sandbox.project = @project
path_list = Sandbox::PathList.new(fixture('banana-lib')) path_list = Sandbox::PathList.new(fixture('banana-lib'))
@spec = fixture_spec('banana-lib/BananaLib.podspec') @spec = fixture_spec('banana-lib/BananaLib.podspec')
file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios)) file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios))
@project.add_pod_group('BananaLib', fixture('banana-lib'))
group = @project.group_for_spec('BananaLib', :source_files) group = @project.group_for_spec('BananaLib', :source_files)
file_accessor.source_files.each do |file| file_accessor.source_files.each do |file|
@project.add_file_reference(file, group) @project.add_file_reference(file, group)
......
...@@ -9,12 +9,13 @@ module Pod ...@@ -9,12 +9,13 @@ module Pod
xcodeproj 'dummy' xcodeproj 'dummy'
end end
@target_definition = @podfile.target_definitions['Pods'] @target_definition = @podfile.target_definitions['Pods']
@project = Project.new(config.sandbox) @project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project config.sandbox.project = @project
path_list = Sandbox::PathList.new(fixture('banana-lib')) path_list = Sandbox::PathList.new(fixture('banana-lib'))
@spec = fixture_spec('banana-lib/BananaLib.podspec') @spec = fixture_spec('banana-lib/BananaLib.podspec')
file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios)) file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios))
@project.add_pod_group('BananaLib', fixture('banana-lib'))
group = @project.group_for_spec('BananaLib', :source_files) group = @project.group_for_spec('BananaLib', :source_files)
file_accessor.source_files.each do |file| file_accessor.source_files.each do |file|
@project.add_file_reference(file, group) @project.add_file_reference(file, group)
......
...@@ -16,7 +16,7 @@ module Pod ...@@ -16,7 +16,7 @@ module Pod
end end
end end
config.sandbox.project = Project.new(config.sandbox) config.sandbox.project = Project.new(config.sandbox.project_path)
Xcodeproj::Project.new(config.sandbox.project_path).save Xcodeproj::Project.new(config.sandbox.project_path).save
@library = AggregateTarget.new(@podfile.target_definitions['Pods'], config.sandbox) @library = AggregateTarget.new(@podfile.target_definitions['Pods'], config.sandbox)
@library.client_root = sample_project_path.dirname @library.client_root = sample_project_path.dirname
......
...@@ -259,6 +259,7 @@ module Pod ...@@ -259,6 +259,7 @@ module Pod
pod_target_ios.stubs(:platform).returns(Platform.new(:ios, '6.0')) pod_target_ios.stubs(:platform).returns(Platform.new(:ios, '6.0'))
pod_target_osx.stubs(:platform).returns(Platform.new(:osx, '10.8')) pod_target_osx.stubs(:platform).returns(Platform.new(:osx, '10.8'))
@installer.stubs(:aggregate_targets).returns([pod_target_ios, pod_target_osx]) @installer.stubs(:aggregate_targets).returns([pod_target_ios, pod_target_osx])
@installer.stubs(:pod_targets).returns([])
@installer.send(:prepare_pods_project) @installer.send(:prepare_pods_project)
build_settings = @installer.pods_project.build_configurations.map(&:build_settings) build_settings = @installer.pods_project.build_configurations.map(&:build_settings)
build_settings.each do |build_setting| build_settings.each do |build_setting|
......
This diff is collapsed.
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