Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
cocoapods
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gengmeiios
cocoapods
Commits
4bb14e58
Commit
4bb14e58
authored
Feb 04, 2013
by
Fabio Pelosin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[WIP][Installer] Adapt for LocalPod refactor
parent
d2b90c07
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
170 additions
and
234 deletions
+170
-234
CHANGELOG.md
CHANGELOG.md
+1
-0
installer.rb
lib/cocoapods/installer.rb
+162
-229
installer_spec.rb
spec/unit/installer_spec.rb
+7
-5
No files found.
CHANGELOG.md
View file @
4bb14e58
...
...
@@ -16,6 +16,7 @@
-
Subspecs now do not inherit the files patterns from the parent spec.
-
The workspace is written only if needed greatly reducing the occasions in
which Xcode asks to revert.
-
Specification hooks are only called when the specification is installed.
###### Specification DSL
...
...
lib/cocoapods/installer.rb
View file @
4bb14e58
...
...
@@ -28,9 +28,11 @@ module Pod
#
class
Installer
autoload
:Analyzer
,
'cocoapods/installer/analyzer'
autoload
:TargetInstaller
,
'cocoapods/installer/target_installer'
autoload
:UserProjectIntegrator
,
'cocoapods/installer/user_project_integrator'
autoload
:Analyzer
,
'cocoapods/installer/analyzer'
autoload
:FileReferencesInstaller
,
'cocoapods/installer/file_references_installer'
autoload
:PodSourceInstaller
,
'cocoapods/installer/pod_source_installer'
autoload
:TargetInstaller
,
'cocoapods/installer/target_installer'
autoload
:UserProjectIntegrator
,
'cocoapods/installer/user_project_integrator'
include
Config
::
Mixin
...
...
@@ -53,9 +55,9 @@ module Pod
# @param [Lockfile] lockfile @see lockfile
#
def
initialize
(
sandbox
,
podfile
,
lockfile
=
nil
)
@sandbox
=
sandbox
@podfile
=
podfile
@lockfile
=
lockfile
@sandbox
=
sandbox
@podfile
=
podfile
@lockfile
=
lockfile
end
# @return [Bool] Whether the installer is in update mode. In update mode
...
...
@@ -80,34 +82,37 @@ module Pod
#
def
install!
analyze
generate_local_pods
generate_names_of_pods_to_install
detect_pods_to_install
prepare_for_legacy_compatibility
prepare_sandbox
install_dependencies
UI
.
section
"Downloading dependencies"
do
create_file_accessors
install_pod_sources
end
UI
.
section
"Generating Pods Project"
do
prepare_pods_project
generate_target_installers
add_file_references_to_pods_project
run_pre_install_hooks
generate_target_support_files
install_file_references
install_targets
run_post_install_hooks
write_pod_project
write_lockfiles
end
integrate_user_project
if
config
.
integrate_targets?
UI
.
section
"Integrating client projects"
do
integrate_user_project
end
end
end
#-------------------------------------------------------------------------#
public
# @!group API
#
# This is the tentative API for the podfile and the specification hooks.
# @!group Installation results
# @return [Analyzer] the analyzer which provides the information about what
# needs to be installed.
...
...
@@ -118,20 +123,6 @@ module Pod
#
attr_reader
:pods_project
# @return [Array<TargetInstaller>]
#
attr_reader
:target_installers
# @return [Hash{TargetDefinition => Array<LocalPod>}] The local pod
# instances grouped by target.
#
attr_reader
:local_pods_by_target
# @return [Array<LocalPod>] The list of LocalPod instances for each
# dependency sorted by name.
#
attr_reader
:local_pods
# @return [Array<String>] The Pods that should be installed.
#
attr_reader
:names_of_pods_to_install
...
...
@@ -141,19 +132,21 @@ module Pod
#
attr_reader
:libraries
#--------------------------------------#
# @return [Array<Specification>] The specifications that where installed.
#
attr_accessor
:installed_specs
#
@!group Hooks compatibility
#
-------------------------------------------------------------------------#
alias
:project
:pods_project
alias
:pods
:local_pods
private
#-------------------------------------------------------------------------#
# TODO: This is recreating the file accessors
# TODO: the file accessor should be initializable without a path list
# @!group Installation steps
private
# @return [void]
#
def
analyze
@analyzer
=
Analyzer
.
new
(
sandbox
,
podfile
,
lockfile
)
@analyzer
.
update_mode
=
update_mode
...
...
@@ -161,46 +154,6 @@ module Pod
@libraries
=
analyzer
.
libraries
end
# Converts the specifications produced by the Resolver in local pods.
#
# The LocalPod class is responsible to handle the concrete representation
# of a specification in the {Sandbox}.
#
# @return [void]
#
# @todo [#535] LocalPods should resolve the path of the specifications
# passing the library as arguments.
#
# @todo Why the local pods are generated by the sandbox? I guess because
# some where pre-downloaded? However the sandbox should just store
# the name of those Pods.
#
def
generate_local_pods
@local_pods_by_target
=
{}
analyzer
.
specs_by_target
.
each
do
|
target_definition
,
specs
|
libray
=
libraries
.
find
{
|
l
|
l
.
target_definition
==
target_definition
}
# TODO the sandbox cached the local pods by target definition
# take into account local? in specification#==
locally_sourced_pods
=
{}
local_pods
=
{}
libray
.
local_pods
=
specs
.
map
do
|
spec
|
if
spec
.
local?
local_pod
=
(
locally_sourced_pods
[
spec
.
root
.
name
]
||=
LocalPod
::
LocalSourcedPod
.
new
(
spec
.
root
,
sandbox
,
target_definition
.
platform
))
local_pod
.
add_specification
(
spec
)
else
local_pod
=
(
local_pods
[
spec
.
root
.
name
]
||=
LocalPod
.
new
(
spec
.
root
,
sandbox
,
target_definition
.
platform
))
local_pod
.
add_specification
(
spec
)
end
local_pod
end
.
uniq
.
compact
end
@local_pods
=
libraries
.
map
(
&
:local_pods
).
flatten
.
uniq
.
sort_by
{
|
pod
|
pod
.
name
.
downcase
}
end
# Computes the list of the Pods that should be installed or reinstalled in
# the {Sandbox}.
#
...
...
@@ -217,17 +170,27 @@ module Pod
# @todo There could be issues with the current implementation regarding
# external specs.
#
def
generate_names_of_pods_to_install
changed_pods_names
=
[]
if
update_mode
changed_pods_names
+=
pods
.
select
do
|
pod
|
pod
.
top_specification
.
version
.
head?
||
resolver
.
pods_from_external_sources
.
include?
(
pod
.
name
)
end
end
changed_pods_names
+=
analyzer
.
sandbox_state
.
added
+
analyzer
.
sandbox_state
.
changed
not_existing_pods
=
local_pods
.
reject
{
|
pod
|
pod
.
exists?
}
@names_of_pods_to_install
=
(
changed_pods_names
+
not_existing_pods
.
map
(
&
:name
)).
uniq
def
detect_pods_to_install
names
=
[]
# TODO
# specs_by_root_name.each do |root_name, specs|
# if update_mode
# if specs.any? { |spec| spec.version.head? } #|| resolver.pods_from_external_sources.include?(root_name)
# @names_of_pods_to_install << root_name
# end
# end
# unless pod_installation_exists?(root_name)
# @names_of_pods_to_install << root_name
# end
# end
# TODO user root name.
names
+=
analyzer
.
sandbox_state
.
added
+
analyzer
.
sandbox_state
.
changed
names
=
names
.
map
{
|
name
|
Specification
.
root_name
(
name
)
}
names
=
names
.
flatten
.
uniq
@names_of_pods_to_install
=
names
end
# Prepares the Pods folder in order to be compatible with the most recent
...
...
@@ -258,6 +221,7 @@ module Pod
sandbox
.
build_headers
.
implode!
sandbox
.
public_headers
.
implode!
# TODO local option
unless
analyzer
.
sandbox_state
.
deleted
.
empty?
UI
.
section
"Removing deleted dependencies"
do
analyzer
.
sandbox_state
.
deleted
.
each
do
|
pod_name
|
...
...
@@ -270,25 +234,6 @@ module Pod
end
end
# @return [void] Install the Pods. If the resolver indicated that a Pod
# should be installed and it exits, it is removed an then
# reinstalled. In any case if the Pod doesn't exits it is
# installed.
#
def
install_dependencies
UI
.
section
"Downloading dependencies"
do
local_pods
.
each
do
|
pod
|
if
names_of_pods_to_install
.
include?
(
pod
.
name
)
UI
.
section
(
"Installing
#{
pod
}
"
.
green
,
"-> "
.
green
)
do
install_local_pod
(
pod
)
end
else
UI
.
section
(
"Using
#{
pod
}
"
,
"-> "
.
green
)
end
end
end
end
# Creates the Pods project from scratch if it doesn't exists.
#
# @return [void]
...
...
@@ -297,70 +242,108 @@ module Pod
#
def
prepare_pods_project
UI
.
message
"- Creating Pods project"
do
@pods_project
=
Pod
::
Project
.
new
(
nil
)
@pods_project
=
Pod
::
Project
.
new
(
sandbox
.
project_path
)
if
config
.
podfile_path
.
exist?
podfile_relative_path
=
config
.
podfile_path
.
relative_path_from
(
sandbox
.
project_path
.
dirname
)
@pods_project
.
add_podfile
(
podfile_relative_path
)
@pods_project
.
add_podfile
(
config
.
podfile_path
)
end
sandbox
.
project
=
@pods_project
end
end
# Creates a target installer for each definition not empty.
#
# @return [void]
#
def
generate_target_installers
@target_installers
=
libraries
.
map
do
|
library
|
unless
library
.
target_definition
.
empty?
TargetInstaller
.
new
(
sandbox
,
library
)
def
create_file_accessors
libraries
.
each
do
|
library
|
library
.
specs
.
each
do
|
spec
|
if
spec
.
local?
pod_root
=
Pathname
.
new
(
spec
.
source
[
:local
]).
expand_path
else
pod_root
=
sandbox
.
pod_dir
(
spec
.
root
.
name
)
end
path_list
=
Sandbox
::
PathList
.
new
(
pod_root
)
file_accessor
=
Sandbox
::
FileAccessor
.
new
(
path_list
,
spec
.
consumer
(
library
.
platform
))
library
.
file_accessors
||=
[]
library
.
file_accessors
<<
file_accessor
end
end
.
compact
end
end
# Adds the source files of the Pods to the Pods project.
#
# The source files are grouped by Pod and in turn by subspec
# (recursively). Pods are generally added to the `Pods` group, however, if
# they have a local source they are added to the `Local Pods` group.
# Downloads, installs the documentation and cleans the sources of the Pods
# which need to be installed.
#
# @return [void]
#
# @todo Clean the groups of the deleted Pods and add only the Pods that
# should be installed.
#
def
add_file_references_to_pods_project
UI
.
message
"- Adding Pods files to Pods project"
do
local_pods
.
each
do
|
pod
|
pod
.
add_file_references_to_project
(
pods_project
)
pod
.
link_headers
unless
pod
.
resources
.
empty?
resources_group
=
pods_project
.
new_group
(
pod
.
name
,
"Resources"
)
pod
.
resources
.
each
do
|
resource
|
resources_group
.
new_file
(
resource
.
relative_path_from
(
sandbox
.
root
))
def
install_pod_sources
@installed_specs
=
[]
root_specs
=
analyzer
.
specifications
.
map
{
|
spec
|
spec
.
root
}
root_specs
.
each
do
|
spec
|
if
names_of_pods_to_install
.
include?
(
spec
.
name
)
UI
.
section
(
"Installing
#{
spec
}
"
.
green
,
"-> "
.
green
)
do
install_source_of_pod
(
spec
.
name
)
end
else
UI
.
section
(
"Using
#{
spec
}
"
,
"-> "
.
green
)
end
end
end
end
# Runs the pre install hooks of the installed specs and of the Podfile.
# Install the Pods. If the resolver indicated that a Pod should be
# installed and it exits, it is removed an then reinstalled. In any case if
# the Pod doesn't exits it is installed.
#
# @return [void]
#
# @todo Run the hooks only for the installed pods.
def
install_source_of_pod
(
pod_name
)
specs_by_platform
=
{}
libraries
.
each
do
|
library
|
specs
=
library
.
specs
.
select
{
|
spec
|
spec
.
root
.
name
==
pod_name
}
unless
specs
.
empty?
specs_by_platform
[
library
.
platform
]
||=
[]
specs_by_platform
[
library
.
platform
].
concat
(
specs
)
end
end
pod_installer
=
PodSourceInstaller
.
new
(
sandbox
,
specs_by_platform
)
root_spec
=
specs_by_platform
.
values
.
flatten
.
first
.
root
local_path
=
root_spec
.
source
[
:local
]
pod_installer
.
local_path
=
Pathname
.
new
(
local_path
).
expand_path
if
local_path
# TODO
pod_installer
.
clean
=
config
.
clean?
pod_installer
.
aggressive_cache
=
config
.
aggressive_cache?
pod_installer
.
generate_docs
=
config
.
generate_docs?
pod_installer
.
install_docs
=
config
.
install_docs?
pod_installer
.
install!
@installed_specs
.
concat
(
specs_by_platform
.
values
.
flatten
)
end
# Runs the pre install hooks of the installed specs and of the Podfile.
#
# @
todo Print a message with the names of the specs.
# @
return [void]
#
def
run_pre_install_hooks
UI
.
message
"- Running pre install hooks"
do
local_pods_by_target
.
each
do
|
target_definition
,
pods
|
pods
.
each
do
|
pod
|
pod
.
top_specification
.
pre_install!
(
pod
,
target_definition
)
end
installed_specs
.
each
do
|
spec
|
pod_data
=
Hooks
::
PodData
.
new
pod_data
.
root
=
sandbox
.
pod_dir
(
spec
.
root
.
name
)
library_data
=
Hooks
::
LibraryData
.
new
executed
=
spec
.
pre_install!
(
pod_data
,
library_data
)
UI
.
message
"-
#{
spec
.
name
}
"
if
executed
end
@podfile
.
pre_install!
(
self
)
installer_data
=
Hooks
::
InstallerData
.
new
installer_data
.
project
=
pods_project
installer_data
.
sandbox
=
sandbox
installer_data
.
libraries
=
libraries
installer_data
.
pods
=
[]
root_specs
=
analyzer
.
specifications
.
map
{
|
spec
|
spec
.
root
}.
uniq
root_specs
.
each
do
|
spec
|
pod_data
=
Hooks
::
PodData
.
new
pod_data
.
root_spec
=
spec
pod_data
.
root
=
nil
#TODO
installer_data
.
pods
=
[]
<<
pod_data
end
executed
=
@podfile
.
pre_install!
(
installer_data
)
UI
.
message
"- Podfile"
if
executed
end
end
...
...
@@ -377,21 +360,40 @@ module Pod
#
def
run_post_install_hooks
UI
.
message
"- Running post install hooks"
do
target_installers
.
each
do
|
target_installer
|
target_installer
.
library
.
specs
.
each
do
|
spec
|
spec
.
post_install!
(
target_installer
)
end
installed_specs
.
each
do
|
spec
|
target_installer_data
=
Hooks
::
TargetInstallerData
.
new
target_installer_data
.
sandbox
=
sandbox
target_installer_data
.
library
=
libraries
.
first
#TODO
executed
=
spec
.
post_install!
(
target_installer_data
)
UI
.
message
"-
#{
spec
.
name
}
"
if
executed
end
@podfile
.
post_install!
(
self
)
installer_data
=
Hooks
::
InstallerData
.
new
installer_data
.
project
=
pods_project
executed
=
@podfile
.
post_install!
(
installer_data
)
UI
.
message
"- Podfile"
if
executed
end
end
# Installs the file references in the Pods project. This is done once per
# Pod as the same file reference might be shared by multiple targets.
#
# @return [void]
#
def
install_file_references
installer
=
FileReferencesInstaller
.
new
(
sandbox
,
libraries
,
pods_project
)
installer
.
install!
end
# Installs the targets of the Pods projects and generates their support
# files.
#
def
generate_target_support_files
# @return [void]
#
def
install_targets
UI
.
message
"- Installing targets"
do
target_installers
.
each
do
|
target_installer
|
libraries
.
each
do
|
library
|
next
if
library
.
target_definition
.
empty?
target_installer
=
TargetInstaller
.
new
(
sandbox
,
library
)
target_installer
.
install!
end
end
...
...
@@ -409,7 +411,7 @@ module Pod
end
end
# Writes the Podfile and the
{Sandbox}
lock files.
# Writes the Podfile and the lock files.
#
# @return [void]
#
...
...
@@ -425,12 +427,10 @@ module Pod
end
end
# Integrates the user project.
#
# The following actions are performed:
# - libraries are added.
# - the build script are added.
# - the xcconfig files are set.
# Integrates the user projects adding the dependencies on the CocoaPods
# libraries, setting them up to use the xcconfigs and performing other
# actions. This step is also reponsible of creating the workspace if
# needed.
#
# @return [void]
#
...
...
@@ -439,77 +439,10 @@ module Pod
# In any case it appears to be a good idea store target definition
# information in the lockfile.
#
# @todo [#588] The resources should be added through a build phase
# instead of using a script.
#
def
integrate_user_project
return
unless
config
.
integrate_targets?
UserProjectIntegrator
.
new
(
podfile
,
sandbox
,
config
.
project_root
,
analyzer
.
libraries
).
integrate!
end
#-------------------------------------------------------------------------#
private
# @!group Helpers
# Downloads, clean and generates the documentation of a pod.
#
# @note The docs need to be generated before cleaning because the
# documentation is created for all the subspecs.
#
# @note In this step we clean also the Pods that have been pre-downloaded
# in AbstractExternalSource#specification_from_sandbox.
#
# @return [void]
#
def
install_local_pod
(
pod
)
unless
sandbox
.
predownloaded_pods
.
include?
(
pod
.
name
)
pod
.
implode
download_pod
(
pod
)
end
generate_docs_if_needed
(
pod
)
pod
.
clean!
if
config
.
clean?
end
# Downloads a Pod forcing the `bleeding edge' version if requested.
#
# @return [void]
#
# @todo Store the source of non specific downloads in the lockfile.
#
def
download_pod
(
pod
)
downloader
=
Downloader
.
for_target
(
pod
.
root
,
pod
.
top_specification
.
source
.
dup
)
downloader
.
cache_root
=
"~/Library/Caches/CocoaPods"
downloader
.
max_cache_size
=
500
downloader
.
agressive_cache
=
config
.
agressive_cache?
if
pod
.
top_specification
.
version
.
head?
downloader
.
download_head
specific_source
=
downloader
.
checkout_options
else
downloader
.
download
specific_source
=
downloader
.
checkout_options
if
downloader
.
specific_options?
end
pod
.
downloaded
=
true
if
specific_source
# store the specific source
end
end
# Generates the documentation of a Pod unless it exists for a given
# version.
#
# @return [void]
#
def
generate_docs_if_needed
(
pod
)
doc_generator
=
Generator
::
Documentation
.
new
(
pod
)
if
(
config
.
generate_docs?
&&
!
doc_generator
.
already_installed?
)
UI
.
section
" > Installing documentation"
doc_generator
.
generate
(
config
.
doc_install?
)
else
UI
.
section
" > Using existing documentation"
end
installation_root
=
config
.
installation_root
libraries
=
analyzer
.
libraries
UserProjectIntegrator
.
new
(
podfile
,
sandbox
,
installation_root
,
libraries
).
integrate!
end
#-------------------------------------------------------------------------#
...
...
spec/unit/installer_spec.rb
View file @
4bb14e58
require
File
.
expand_path
(
'../../spec_helper'
,
__FILE__
)
# TODO add tests for multiple targets!
# @return [Lockfile]
#
def
generate_lockfile
...
...
@@ -26,7 +28,7 @@ module Pod
# before do
# @sandbox = temporary_sandbox
# config.repos_dir = fixture('spec-repos')
# config.
project_pods
_root = @sandbox.root
# config.
sandbox
_root = @sandbox.root
# FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
# end
#
...
...
@@ -38,7 +40,7 @@ module Pod
describe
"Concerning pre-installation computations"
do
# @sandbox = temporary_sandbox
# config.
project_pods
_root = temporary_sandbox.root
# config.
sandbox
_root = temporary_sandbox.root
# FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
# resolver = Resolver.new(podfile, nil, @sandbox)
...
...
@@ -80,7 +82,7 @@ module Pod
# end
# @sandbox = temporary_sandbox
# config.
project_pods
_root = temporary_sandbox.root
# config.
sandbox
_root = temporary_sandbox.root
# FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
# @installer = Installer.new(@sandbox, podfile)
# target_installer = @installer.target_installers.first
...
...
@@ -118,7 +120,7 @@ module Pod
# before do
# sandbox = temporary_sandbox
# Config.instance.
project_pods
_root = sandbox.root
# Config.instance.
sandbox
_root = sandbox.root
# Config.instance.integrate_targets = false
# podspec_path = fixture('integration/Reachability/Reachability.podspec')
# podfile = Podfile.new do
...
...
@@ -166,7 +168,7 @@ module Pod
# before do
# sandbox = temporary_sandbox
# Config.instance.
project_pods
_root = sandbox.root
# Config.instance.
sandbox
_root = sandbox.root
# Config.instance.integrate_targets = false
# podspec_path = fixture('chameleon')
# podfile = Podfile.new do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment