8000 Creates a stage sandbox and sandbox dir cleaner step. by sebastianv1 · Pull Request #8339 · CocoaPods/CocoaPods · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Creates a stage sandbox and sandbox dir cleaner step. #8339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 40 additions & 30 deletions lib/cocoapods/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,18 @@ module Pod
# source control.
#
class Installer
autoload :Analyzer, 'cocoapods/installer/analyzer'
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'
autoload :PodfileValidator, 'cocoapods/installer/podfile_validator'
autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
autoload :PodSourcePreparer, 'cocoapods/installer/pod_source_preparer'
autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
autoload :Xcode, 'cocoapods/installer/xcode'
autoload :Analyzer, 'cocoapods/installer/analyzer'
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'
autoload :PodfileValidator, 'cocoapods/installer/podfile_validator'
autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
autoload :PodSourcePreparer, 'cocoapods/installer/pod_source_preparer'
autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
autoload :Xcode, 'cocoapods/installer/xcode'
autoload :SandboxHeaderPathsInstaller, 'cocoapods/installer/sandbox_header_paths_installer'
autoload :SandboxDirCleaner, 'cocoapods/installer/sandbox_dir_cleaner'

include Config::Mixin

Expand Down Expand Up @@ -171,7 +173,6 @@ def resolve_dependencies
UI.section 'Analyzing dependencies' do
analyze(analyzer)
validate_build_configurations
clean_sandbox
end

UI.section 'Verifying no changes' do
Expand All @@ -190,6 +191,20 @@ def download_dependencies
end
end

# Stages the sandbox after analysis.
#
# @param [Sandbox] sandbox
# The sandbox to stage.
#
# @param [Array<PodTarget>] pod_targets
# The list of all pod targets.
#
# @return [void]
#
def stage_sandbox(sandbox, pod_targets)
SandboxHeaderPathsInstaller.new(sandbox, pod_targets).install!
end

#-------------------------------------------------------------------------#

# @!group Pods Project Generation
Expand All @@ -206,7 +221,15 @@ def create_generator(generate_multiple_pod_projects = false)

# Generates the Xcode project(s) that go inside the `Pods/` directory.
#
def generate_pods_project(generator = create_generator(installation_options.generate_multiple_pod_projects))
def generate_pods_project
stage_sandbox(sandbox, pod_targets)
clean_sandbox(pod_targets)
create_and_save_projects
write_lockfiles
SandboxDirCleaner.new(sandbox, pod_targets, aggregate_targets).clean!
end

def create_and_save_projects(generator = create_generator(installation_options.generate_multiple_pod_projects))
UI.section 'Generating Pods project' do
pod_project_generation_result = generator.generate!
@target_installation_results = pod_project_generation_result.target_installation_results
Expand All @@ -227,8 +250,6 @@ def generate_pods_project(generator = create_generator(installation_options.gene
all_projects_by_pod_targets.each do |project, pod_targets|
generator.share_development_pod_schemes(project, development_pod_targets(pod_targets))
end

write_lockfiles
end
end

Expand Down Expand Up @@ -314,26 +335,15 @@ def validate_build_configurations
end
end

# @return [void] In this step we clean all the folders that will be
# regenerated from scratch and any file which might not be
# overwritten.
#
# @todo [#247] Clean the headers of only the pods to install.
# @return [void] In this step we clean all the header folders for pod targets that will be
# regenerated from scratch and cleanup any pods that have been removed.
#
def clean_sandbox
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all the old functionality now seems to be replicated in SandboxDirCleaner#clean!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sets up incremental since clean_sandbox will only take in a subset of all pod targets to clean.

sandbox.public_headers.implode!
target_support_dirs = sandbox.target_support_files_root.children.select(&:directory?)
def clean_sandbox(pod_targets)
pod_targets.each do |pod_target|
pod_target.build_headers.implode!
target_support_dirs.delete(pod_target.support_files_dir)
pod_target.build_headers.implode_path!(pod_target.headers_sandbox)
sandbox.public_headers.implode_path!(pod_target.headers_sandbox)
end

aggregate_targets.each do |aggregate_target|
target_support_dirs.delete(aggregate_target.support_files_dir)
end

target_support_dirs.each { |dir| FileUtils.rm_rf(dir) }

unless sandbox_state.deleted.empty?
title_options = { :verbose_prefix => '-> '.red }
sandbox_state.deleted.each do |pod_name|
Expand Down
89 changes: 89 additions & 0 deletions lib/cocoapods/installer/sandbox_dir_cleaner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
module Pod
class Installer
# Cleans up the sandbox directory by removing stale target support files and headers.
#
class SandboxDirCleaner
# @return [Sandbox] The sandbox directory that will be cleaned.
#
attr_reader :sandbox

# @return [Array<PodTarget>]
# The list of all pod targets that will be installed into the Sandbox.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this correct or copy pasta?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct in that I wrote it :) The list of pod targets that will be installed are used to compute which folders need to be deleted.

#
attr_reader :pod_targets

# @return [Array<AggregateTarget>]
# The list of all aggregate targets that will be installed into the Sandbox.
#
attr_reader :aggregate_targets

# Initialize a new instance
#
# @param [Sandbox] sandbox @see #sandbox
# @param [Array<PodTarget>] pod_targets @see #pod_targets
# @param [Array<AggregateTarget>] aggregate_targets @see #aggregate_targets
#
def initialize(sandbox, pod_targets, aggregate_targets)
@sandbox = sandbox
@pod_targets = pod_targets
@aggregate_targets = aggregate_targets
end

def clean!
UI.message('Cleaning up sandbox directory') do
# Clean up Target Support Files Directory
target_support_dirs_to_install = (pod_targets + aggregate_targets).map(&:support_files_dir)
target_support_dirs = sandbox_target_support_dirs

removed_target_support_dirs = target_support_dirs - target_support_dirs_to_install
removed_target_support_dirs.each { |dir| remove_dir(dir) }

# Clean up Sandbox Headers Directory
sandbox_private_headers_to_install = pod_targets.flat_map do |pod_target|
if pod_target.header_mappings_by_file_accessor.empty?
[]
else
[pod_target.build_headers.root.join(pod_target.headers_sandbox)]
end
end
sandbox_public_headers_to_install = pod_targets.flat_map do |pod_target|
if pod_target.public_header_mappings_by_file_accessor.empty?
[]
else
[sandbox.public_headers.root.join(pod_target.headers_sandbox)]
end
end

removed_sandbox_public_headers = sandbox_public_headers - sandbox_public_headers_to_install
removed_sandbox_public_headers.each { |path| remove_dir(path) }

removed_sandbox_private_headers = sandbox_private_headers(pod_targets) - sandbox_private_headers_to_install
removed_sandbox_private_headers.each { |path| remove_dir(path) }
end
end

private

def sandbox_target_support_dirs
child_directories_of(sandbox.target_support_files_root)
end

def sandbox_private_headers(pod_targets)
pod_targets.flat_map { |pod_target| child_directories_of(pod_target.build_headers.root) }.uniq
end

def sandbox_public_headers
child_directories_of(sandbox.public_headers.root)
end

def child_directories_of(dir)
return [] unless dir.exist?
dir.children.select(&:directory?)
end

def remove_dir(path)
FileUtils.rm_rf(path)
end
end
end
end
45 changes: 45 additions & 0 deletions lib/cocoapods/installer/sandbox_header_paths_installer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module Pod
class Installer
# Adds all the search paths into the sandbox HeaderStore and each pod target's HeaderStore.
#
class SandboxHeaderPathsInstaller
# @return [Sandbox] The sandbox to use for this analysis.
#
attr_reader :sandbox

# @return [Array<PodTarget>] The list of pod targets to analyze.
#
attr_reader :pod_targets

# Initialize a new instance
#
# @param [Sandbox] sandbox @see #sandbox
# @param [Array<PodTarget>] pod_targets @see #pod_targets
#
def initialize(sandbox, pod_targets)
@pod_targets = pod_targets
@sandbox = sandbox
end

def install!
# Link all pod target header search paths into the HeaderStore.
pod_targets.each do |pod_target|
next if pod_target.build_as_framework? && pod_target.should_build?
install_target(pod_target)
end
end

private

def install_target(pod_target)
pod_target_header_mappings = pod_target.header_mappings_by_file_accessor.values
public_header_mappings = pod_target.public_header_mappings_by_file_accessor.values
added_build_headers = !pod_target_header_mappings.all?(&:empty?)
added_public_headers = !public_header_mappings.all?(&:empty?)

pod_target.build_headers.add_search_path(pod_target.headers_sandbox, pod_target.platform) if added_build_headers
sandbox.public_headers.add_search_path(pod_target.headers_sandbox, pod_target.platform) if added_public_headers
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -146,29 +146,19 @@ def link_headers
# sandbox.
next if pod_target.build_as_framework? && pod_target.should_build?

headers_sandbox = Pathname.new(pod_target.pod_name)
added_build_headers = false
added_public_headers = false

file_accessors = pod_target.file_accessors.reject { |fa| fa.spec.non_library_specification? }
file_accessors.each do |file_accessor|
# Private headers will always end up in Pods/Headers/Private/PodA/*.h
# This will allow for `""` imports to work.
header_mappings(headers_sandbox, file_accessor, file_accessor.headers).each do |namespaced_path, files|
added_build_headers = true
pod_target_header_mappings = pod_target.header_mappings_by_file_accessor.values
pod_target_header_mappings.each do |header_mappings|
header_mappings.each do |namespaced_path, files|
pod_target.build_headers.add_files(namespaced_path, files)
end
end

# Public headers on the other hand will be added in Pods/Headers/Public/PodA/PodA/*.h
# The extra folder is intentional in order for `<>` imports to work.
header_mappings(headers_sandbox, file_accessor, file_accessor.public_headers).each do |namespaced_path, files|
added_public_headers = true
public_header_mappings = pod_target.public_header_mappings_by_file_accessor.values
public_header_mappings.each do |header_mappings|
header_mappings.each do |namespaced_path, files|
sandbox.public_headers.add_files(namespaced_path, files)
end
end

pod_target.build_headers.add_search_path(headers_sandbox, pod_target.platform) if added_build_headers
sandbox.public_headers.add_search_path(headers_sandbox, pod_target.platform) if added_public_headers
end
end
end
Expand Down Expand Up @@ -294,44 +284,6 @@ def common_path(paths)
return result unless result.to_s == '' || result.to_s == '/'
end

# Computes the destination sub-directory in the sandbox
#
# @param [Pathname] headers_sandbox
# The sandbox where the header links should be stored for this
# Pod.
#
# @param [Sandbox::FileAccessor] file_accessor
# The consumer file accessor for which the headers need to be
# linked.
#
# @param [Array<Pathname>] headers
# The absolute paths of the headers which need to be mapped.
#
# @return [Hash{Pathname => Array<Pathname>}] A hash containing the
# headers folders as the keys and the absolute paths of the
# header files as the values.
#
def header_mappings(headers_sandbox, file_accessor, headers)
consumer = file_accessor.spec_consumer
header_mappings_dir = consumer.header_mappings_dir
dir = headers_sandbox
dir += consumer.header_dir if consumer.header_dir

mappings = {}
headers.each do |header|
next if header.to_s.include?('.framework/')

sub_dir = dir
if header_mappings_dir
relative_path = header.relative_path_from(file_accessor.path_list.root + header_mappings_dir)
sub_dir += relative_path.dirname
end
mappings[sub_dir] ||= []
mappings[sub_dir] << header
end
mappings
end

#-----------------------------------------------------------------------#
end
end
Expand Down
2 changes: 0 additions & 2 deletions lib/cocoapods/sandbox.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ def clean_pod(name)
# be regenerated and ensuring that the directories exists.
#
def prepare
FileUtils.rm_rf(headers_root)

FileUtils.mkdir_p(headers_root)
FileUtils.mkdir_p(sources_root)
FileUtils.mkdir_p(specifications_root)
Expand Down
15 changes: 13 additions & 2 deletions lib/cocoapods/sandbox/headers_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,26 @@ def search_paths(platform, target_name = nil, use_modular_headers = false)
end.tap(&:uniq!).freeze
end

# Removes the directory as it is regenerated from scratch during each
# installation.
# Removes the entire root directory.
#
# @return [void]
#
def implode!
root.rmtree if root.exist?
end

# Removes the directory at the given path relative to the root.
#
# @param [Pathname] path
# The path used to join with #root and remove.
#
# @return [void]
#
def implode_path!(path)
path = root.join(path)
path.rmtree if path.exist?
end

#-----------------------------------------------------------------------#

public
Expand Down
Loading
0