cocoapods 0.16.4 → 0.17.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +108 -0
- data/README.md +3 -3
- data/bin/pod +1 -1
- data/lib/cocoapods.rb +31 -31
- data/lib/cocoapods/command.rb +62 -107
- data/lib/cocoapods/command/inter_process_communication.rb +103 -0
- data/lib/cocoapods/command/list.rb +45 -44
- data/lib/cocoapods/command/outdated.rb +28 -25
- data/lib/cocoapods/command/project.rb +90 -0
- data/lib/cocoapods/command/push.rb +50 -32
- data/lib/cocoapods/command/repo.rb +125 -155
- data/lib/cocoapods/command/search.rb +23 -12
- data/lib/cocoapods/command/setup.rb +103 -64
- data/lib/cocoapods/command/spec.rb +329 -90
- data/lib/cocoapods/config.rb +197 -44
- data/lib/cocoapods/downloader.rb +47 -34
- data/lib/cocoapods/executable.rb +98 -41
- data/lib/cocoapods/external_sources.rb +325 -0
- data/lib/cocoapods/file_list.rb +8 -1
- data/lib/cocoapods/gem_version.rb +7 -0
- data/lib/cocoapods/generator/acknowledgements.rb +71 -7
- data/lib/cocoapods/generator/acknowledgements/markdown.rb +10 -9
- data/lib/cocoapods/generator/acknowledgements/plist.rb +9 -8
- data/lib/cocoapods/generator/copy_resources_script.rb +2 -2
- data/lib/cocoapods/generator/documentation.rb +153 -37
- data/lib/cocoapods/generator/prefix_header.rb +82 -0
- data/lib/cocoapods/generator/target_header.rb +58 -0
- data/lib/cocoapods/generator/xcconfig.rb +130 -0
- data/lib/cocoapods/hooks/installer_representation.rb +123 -0
- data/lib/cocoapods/hooks/library_representation.rb +79 -0
- data/lib/cocoapods/hooks/pod_representation.rb +74 -0
- data/lib/cocoapods/installer.rb +398 -147
- data/lib/cocoapods/installer/analyzer.rb +556 -0
- data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
- data/lib/cocoapods/installer/file_references_installer.rb +179 -0
- data/lib/cocoapods/installer/pod_source_installer.rb +289 -0
- data/lib/cocoapods/installer/target_installer.rb +307 -112
- data/lib/cocoapods/installer/user_project_integrator.rb +140 -176
- data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +193 -0
- data/lib/cocoapods/library.rb +195 -0
- data/lib/cocoapods/open_uri.rb +16 -14
- data/lib/cocoapods/project.rb +175 -52
- data/lib/cocoapods/resolver.rb +151 -164
- data/lib/cocoapods/sandbox.rb +276 -54
- data/lib/cocoapods/sandbox/file_accessor.rb +210 -0
- data/lib/cocoapods/sandbox/headers_store.rb +96 -0
- data/lib/cocoapods/sandbox/path_list.rb +178 -0
- data/lib/cocoapods/sources_manager.rb +218 -0
- data/lib/cocoapods/user_interface.rb +82 -18
- data/lib/cocoapods/{command → user_interface}/error_report.rb +5 -5
- data/lib/cocoapods/validator.rb +379 -0
- metadata +74 -55
- data/lib/cocoapods/command/install.rb +0 -55
- data/lib/cocoapods/command/linter.rb +0 -317
- data/lib/cocoapods/command/update.rb +0 -25
- data/lib/cocoapods/dependency.rb +0 -285
- data/lib/cocoapods/downloader/git.rb +0 -276
- data/lib/cocoapods/downloader/http.rb +0 -99
- data/lib/cocoapods/downloader/mercurial.rb +0 -26
- data/lib/cocoapods/downloader/subversion.rb +0 -42
- data/lib/cocoapods/local_pod.rb +0 -620
- data/lib/cocoapods/lockfile.rb +0 -274
- data/lib/cocoapods/platform.rb +0 -127
- data/lib/cocoapods/podfile.rb +0 -551
- data/lib/cocoapods/source.rb +0 -223
- data/lib/cocoapods/specification.rb +0 -579
- data/lib/cocoapods/specification/set.rb +0 -175
- data/lib/cocoapods/specification/statistics.rb +0 -112
- data/lib/cocoapods/user_interface/ui_pod.rb +0 -130
- data/lib/cocoapods/version.rb +0 -26
@@ -0,0 +1,130 @@
|
|
1
|
+
module Pod
|
2
|
+
module Generator
|
3
|
+
|
4
|
+
# Generates an xcconfig file for each target of the Pods project. The
|
5
|
+
# configuration file should be used by the user target as well.
|
6
|
+
#
|
7
|
+
class XCConfig
|
8
|
+
|
9
|
+
# @return [Sandbox] the sandbox where the Pods project is installed.
|
10
|
+
#
|
11
|
+
attr_reader :sandbox
|
12
|
+
|
13
|
+
# @return [Array<Specification::Consumer>] the consumers for the
|
14
|
+
# specifications of the library which needs the xcconfig.
|
15
|
+
#
|
16
|
+
attr_reader :spec_consumers
|
17
|
+
|
18
|
+
# @return [String] the relative path of the Pods root respect the user
|
19
|
+
# project that should be integrated by this library.
|
20
|
+
#
|
21
|
+
attr_reader :relative_pods_root
|
22
|
+
|
23
|
+
# @param [Sandbox] sandbox @see sandbox
|
24
|
+
# @param [Array<LocalPod>] pods @see pods
|
25
|
+
# @param [String] relative_pods_root @see relative_pods_root
|
26
|
+
#
|
27
|
+
def initialize(sandbox, spec_consumers, relative_pods_root)
|
28
|
+
@sandbox = sandbox
|
29
|
+
@spec_consumers = spec_consumers
|
30
|
+
@relative_pods_root = relative_pods_root
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Bool] whether the Podfile specifies to add the `-fobjc-arc`
|
34
|
+
# flag for compatibility.
|
35
|
+
#
|
36
|
+
attr_accessor :set_arc_compatibility_flag
|
37
|
+
|
38
|
+
#-----------------------------------------------------------------------#
|
39
|
+
|
40
|
+
# Generates the xcconfig for the library.
|
41
|
+
#
|
42
|
+
# @return [Xcodeproj::Config]
|
43
|
+
#
|
44
|
+
# @note The value `PODS_HEADERS_SEARCH_PATHS` is used to store the headers
|
45
|
+
# so xcconfig can reference the variable.
|
46
|
+
#
|
47
|
+
def generate
|
48
|
+
ld_flags = '-ObjC'
|
49
|
+
if set_arc_compatibility_flag && spec_consumers.any? { |consumer| consumer.requires_arc }
|
50
|
+
ld_flags << ' -fobjc-arc'
|
51
|
+
end
|
52
|
+
|
53
|
+
@xcconfig = Xcodeproj::Config.new({
|
54
|
+
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
|
55
|
+
'OTHER_LDFLAGS' => ld_flags,
|
56
|
+
'HEADER_SEARCH_PATHS' => '${PODS_HEADERS_SEARCH_PATHS}',
|
57
|
+
'PODS_ROOT' => relative_pods_root,
|
58
|
+
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_PUBLIC_HEADERS_SEARCH_PATHS}',
|
59
|
+
'PODS_BUILD_HEADERS_SEARCH_PATHS' => quote(sandbox.build_headers.search_paths),
|
60
|
+
'PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quote(sandbox.public_headers.search_paths),
|
61
|
+
})
|
62
|
+
|
63
|
+
spec_consumers.each do |consumer|
|
64
|
+
@xcconfig.merge!(consumer.xcconfig);
|
65
|
+
@xcconfig.libraries.merge(consumer.libraries);
|
66
|
+
@xcconfig.frameworks.merge(consumer.frameworks);
|
67
|
+
@xcconfig.weak_frameworks.merge(consumer.weak_frameworks);
|
68
|
+
end
|
69
|
+
|
70
|
+
@xcconfig
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [Xcodeproj::Config] The generated xcconfig.
|
74
|
+
#
|
75
|
+
attr_reader :xcconfig
|
76
|
+
|
77
|
+
# @return [Hash] The settings of the xcconfig that the Pods project
|
78
|
+
# needs to override.
|
79
|
+
#
|
80
|
+
def self.pods_project_settings
|
81
|
+
{ 'PODS_ROOT' => '${SRCROOT}',
|
82
|
+
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_BUILD_HEADERS_SEARCH_PATHS}' }
|
83
|
+
end
|
84
|
+
|
85
|
+
# Generates and saves the xcconfig to the given path.
|
86
|
+
#
|
87
|
+
# @param [Pathname] path
|
88
|
+
# the path where the prefix header should be stored.
|
89
|
+
#
|
90
|
+
# @return [void]
|
91
|
+
#
|
92
|
+
def save_as(path)
|
93
|
+
path.open('w') { |file| file.write(generate) }
|
94
|
+
end
|
95
|
+
|
96
|
+
#-----------------------------------------------------------------------#
|
97
|
+
|
98
|
+
# @!group Private helpers.
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
# @return [String] the default linker flags. `-ObjC` is always included
|
103
|
+
# while `-fobjc-arc` is included only if requested in the
|
104
|
+
# Podfile.
|
105
|
+
#
|
106
|
+
def default_ld_flags
|
107
|
+
flags = %w[ -ObjC ]
|
108
|
+
requires_arc = pods.any? { |pod| pod.requires_arc? }
|
109
|
+
if requires_arc && set_arc_compatibility_flag
|
110
|
+
flags << '-fobjc-arc'
|
111
|
+
end
|
112
|
+
flags.join(" ")
|
113
|
+
end
|
114
|
+
|
115
|
+
# Converts an array of strings to a single string where the each string
|
116
|
+
# is surrounded by double quotes and separated by a space. Used to
|
117
|
+
# represent strings in a xcconfig file.
|
118
|
+
#
|
119
|
+
# @param [Array<String>] strings
|
120
|
+
# a list of strings.
|
121
|
+
#
|
122
|
+
# @return [String] the resulting string.
|
123
|
+
#
|
124
|
+
def quote(strings)
|
125
|
+
strings.sort.map { |s| %W|"#{s}"| }.join(" ")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module Pod
|
2
|
+
|
3
|
+
class Podfile
|
4
|
+
def config
|
5
|
+
UI.warn "Podfile#config is deprecated. The config is accessible from " \
|
6
|
+
"the parameter passed to the hooks"
|
7
|
+
Config.instance
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module Hooks
|
12
|
+
|
13
|
+
# The installer representation to pass to the hooks.
|
14
|
+
#
|
15
|
+
class InstallerRepresentation
|
16
|
+
|
17
|
+
public
|
18
|
+
|
19
|
+
# @!group Public Hooks API
|
20
|
+
|
21
|
+
# @return [Pathname] The root of the sandbox.
|
22
|
+
#
|
23
|
+
def sandbox_root
|
24
|
+
installer.sandbox.root
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Pod::Project] the `Pods/Pods.xcodeproj` project.
|
28
|
+
#
|
29
|
+
def project
|
30
|
+
installer.pods_project
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Array<PodRepresentation>] The representation of the Pods.
|
34
|
+
#
|
35
|
+
def pods
|
36
|
+
installer.pod_reps
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Array<LibraryRepresentation>] The representation of the
|
40
|
+
# libraries.
|
41
|
+
#
|
42
|
+
def libraries
|
43
|
+
installer.library_reps
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Hash{LibraryRepresentation => Array<Specification>}] The
|
47
|
+
# specifications grouped by target definition.
|
48
|
+
#
|
49
|
+
def specs_by_lib
|
50
|
+
result = {}
|
51
|
+
installer.libraries.each do |lib|
|
52
|
+
result[installer.library_rep(lib)] = lib.specs
|
53
|
+
end
|
54
|
+
result
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Hash{LibraryRepresentation => Array<PodRepresentation>}] The
|
58
|
+
# local pod instances grouped by target.
|
59
|
+
#
|
60
|
+
def pods_by_lib
|
61
|
+
result = {}
|
62
|
+
installer.libraries.each do |lib|
|
63
|
+
pod_names = lib.specs.map { |spec| spec.root.name }.uniq
|
64
|
+
pod_reps = pods.select { |rep| pod_names.include?(rep.name) }
|
65
|
+
result[lib.target_definition] = pod_reps
|
66
|
+
end
|
67
|
+
result
|
68
|
+
end
|
69
|
+
|
70
|
+
#-----------------------------------------------------------------------#
|
71
|
+
public
|
72
|
+
|
73
|
+
# @!group Compatibility
|
74
|
+
#
|
75
|
+
# The following aliases provides compatibility with CP < 0.17
|
76
|
+
|
77
|
+
alias :target_installers :libraries
|
78
|
+
alias :specs_by_target :specs_by_lib
|
79
|
+
alias :local_pods_by_target :pods_by_lib
|
80
|
+
|
81
|
+
#-----------------------------------------------------------------------#
|
82
|
+
|
83
|
+
public
|
84
|
+
|
85
|
+
# @!group Unsafe Hooks API
|
86
|
+
#
|
87
|
+
# The interface of the following objects might change at any time.
|
88
|
+
# If there some information which is needed, please open an issue.
|
89
|
+
|
90
|
+
# @return [Sandbox] sandbox the sandbox where the support files should
|
91
|
+
# be generated.
|
92
|
+
#
|
93
|
+
def sandbox
|
94
|
+
installer.sandbox
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [Config] The config singleton used for the installation.
|
98
|
+
#
|
99
|
+
def config
|
100
|
+
Config.instance
|
101
|
+
end
|
102
|
+
|
103
|
+
# @return [Installer] The installer described by this instance.
|
104
|
+
#
|
105
|
+
attr_reader :installer
|
106
|
+
|
107
|
+
#-----------------------------------------------------------------------#
|
108
|
+
|
109
|
+
# @!group Private implementation
|
110
|
+
|
111
|
+
# @param [Installer] installer @see installer
|
112
|
+
#
|
113
|
+
def initialize(installer)
|
114
|
+
@installer = installer
|
115
|
+
end
|
116
|
+
|
117
|
+
#-----------------------------------------------------------------------#
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Pod
|
2
|
+
module Hooks
|
3
|
+
class LibraryRepresentation
|
4
|
+
|
5
|
+
# Stores the information of the target installer
|
6
|
+
|
7
|
+
#-----------------------------------------------------------------------#
|
8
|
+
|
9
|
+
# @return [String] The name of the Pods library.
|
10
|
+
#
|
11
|
+
def name
|
12
|
+
library.name
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Array<Dependency>] The dependencies of this library.
|
16
|
+
#
|
17
|
+
def dependencies
|
18
|
+
target_definition.dependencies
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Pathname] The path of the prefix_header
|
22
|
+
#
|
23
|
+
def prefix_header_filename
|
24
|
+
library.prefix_header_path
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Project] The Pods project of the sandbox.
|
28
|
+
#
|
29
|
+
def project
|
30
|
+
sandbox.project
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [TargetDefinition] The target definition of the library.
|
34
|
+
#
|
35
|
+
def target_definition
|
36
|
+
library.target_definition
|
37
|
+
end
|
38
|
+
|
39
|
+
#-----------------------------------------------------------------------#
|
40
|
+
|
41
|
+
public
|
42
|
+
|
43
|
+
# @!group Unsafe Hooks API
|
44
|
+
|
45
|
+
# @return [Sandbox] sandbox the sandbox where the support files should
|
46
|
+
# be generated.
|
47
|
+
#
|
48
|
+
attr_reader :sandbox
|
49
|
+
|
50
|
+
# @return [Library] The library whose target needs to be generated.
|
51
|
+
#
|
52
|
+
attr_reader :library
|
53
|
+
|
54
|
+
# @return [PBXNativeTarget] The target generated by the installation
|
55
|
+
# process.
|
56
|
+
#
|
57
|
+
def target
|
58
|
+
library.target
|
59
|
+
end
|
60
|
+
|
61
|
+
#-----------------------------------------------------------------------#
|
62
|
+
|
63
|
+
# @!group Private implementation
|
64
|
+
|
65
|
+
# @param [Sandbox] sandbox @see sandbox
|
66
|
+
# @param [Library] library @see library
|
67
|
+
#
|
68
|
+
def initialize(sandbox, library)
|
69
|
+
@sandbox = sandbox
|
70
|
+
@library = library
|
71
|
+
end
|
72
|
+
|
73
|
+
#-----------------------------------------------------------------------#
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Pod
|
2
|
+
|
3
|
+
class Specification
|
4
|
+
def config
|
5
|
+
UI.warn "Specification#config is deprecated. The config is accessible from " \
|
6
|
+
"the parameter passed to the hooks"
|
7
|
+
Config.instance
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module Hooks
|
12
|
+
|
13
|
+
# Stores the information of the Installer for the hooks
|
14
|
+
#
|
15
|
+
class PodRepresentation
|
16
|
+
|
17
|
+
# @return [String]
|
18
|
+
#
|
19
|
+
attr_accessor :name
|
20
|
+
|
21
|
+
# @return [Version]
|
22
|
+
#
|
23
|
+
def version
|
24
|
+
root_spec.version
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Specification]
|
28
|
+
#
|
29
|
+
def root_spec
|
30
|
+
file_accessors.first.spec.root
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Array<Specification>]
|
34
|
+
#
|
35
|
+
def specs
|
36
|
+
file_accessors.map(&:spec).uniq
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Pathname]
|
40
|
+
#
|
41
|
+
def root
|
42
|
+
file_accessors.first.path_list.root
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Array<Pathname>]
|
46
|
+
#
|
47
|
+
def source_files
|
48
|
+
file_accessors.map(&:source_files).flatten.uniq
|
49
|
+
end
|
50
|
+
|
51
|
+
#-----------------------------------------------------------------------#
|
52
|
+
|
53
|
+
# @!group Private implementation
|
54
|
+
|
55
|
+
# @param [Installer] installer @see installer
|
56
|
+
#
|
57
|
+
def initialize(name, file_accessors)
|
58
|
+
@name = name
|
59
|
+
@file_accessors = file_accessors
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
root_spec.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
attr_reader :file_accessors
|
69
|
+
|
70
|
+
#-----------------------------------------------------------------------#
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/cocoapods/installer.rb
CHANGED
@@ -1,216 +1,467 @@
|
|
1
|
-
require 'colored'
|
2
|
-
|
3
1
|
module Pod
|
2
|
+
|
3
|
+
# The Installer is responsible of taking a Podfile and transform it in the
|
4
|
+
# Pods libraries. It also integrates the user project so the Pods
|
5
|
+
# libraries can be used out of the box.
|
6
|
+
#
|
7
|
+
# The Installer is capable of doing incremental updates to an existing Pod
|
8
|
+
# installation.
|
9
|
+
#
|
10
|
+
# The Installer gets the information that it needs mainly from 3 files:
|
11
|
+
#
|
12
|
+
# - Podfile: The specification written by the user that contains
|
13
|
+
# information about targets and Pods.
|
14
|
+
# - Podfile.lock: Contains information about the pods that were previously
|
15
|
+
# installed and in concert with the Podfile provides information about
|
16
|
+
# which specific version of a Pod should be installed. This file is
|
17
|
+
# ignored in update mode.
|
18
|
+
# - Manifest.lock: A file contained in the Pods folder that keeps track of
|
19
|
+
# the pods installed in the local machine. This files is used once the
|
20
|
+
# exact versions of the Pods has been computed to detect if that version
|
21
|
+
# is already installed. This file is not intended to be kept under source
|
22
|
+
# control and is a copy of the Podfile.lock.
|
23
|
+
#
|
24
|
+
# The Installer is designed to work in environments where the Podfile folder
|
25
|
+
# is under source control and environments where it is not. The rest of the
|
26
|
+
# files, like the user project and the workspace are assumed to be under
|
27
|
+
# source control.
|
28
|
+
#
|
4
29
|
class Installer
|
5
|
-
|
6
|
-
autoload :
|
30
|
+
|
31
|
+
autoload :Analyzer, 'cocoapods/installer/analyzer'
|
32
|
+
autoload :FileReferencesInstaller, 'cocoapods/installer/file_references_installer'
|
33
|
+
autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
|
34
|
+
autoload :TargetInstaller, 'cocoapods/installer/target_installer'
|
35
|
+
autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
|
7
36
|
|
8
37
|
include Config::Mixin
|
9
38
|
|
10
|
-
|
39
|
+
# @return [Sandbox] The sandbox where the Pods should be installed.
|
40
|
+
#
|
41
|
+
attr_reader :sandbox
|
42
|
+
|
43
|
+
# @return [Podfile] The Podfile specification that contains the information
|
44
|
+
# of the Pods that should be installed.
|
45
|
+
#
|
46
|
+
attr_reader :podfile
|
47
|
+
|
48
|
+
# @return [Lockfile] The Lockfile that stores the information about the
|
49
|
+
# Pods previously installed on any machine.
|
50
|
+
#
|
51
|
+
attr_reader :lockfile
|
52
|
+
|
53
|
+
# @param [Sandbox] sandbox @see sandbox
|
54
|
+
# @param [Podfile] podfile @see podfile
|
55
|
+
# @param [Lockfile] lockfile @see lockfile
|
56
|
+
#
|
57
|
+
def initialize(sandbox, podfile, lockfile = nil)
|
58
|
+
@sandbox = sandbox
|
59
|
+
@podfile = podfile
|
60
|
+
@lockfile = lockfile
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Bool] Whether the installer is in update mode. In update mode
|
64
|
+
# the contents of the Lockfile are not taken into account for
|
65
|
+
# deciding what Pods to install.
|
66
|
+
#
|
67
|
+
attr_accessor :update_mode
|
68
|
+
|
69
|
+
# Installs the Pods.
|
70
|
+
#
|
71
|
+
# The installation process of is mostly linear with few minor complications
|
72
|
+
# to keep in mind:
|
73
|
+
#
|
74
|
+
# - The stored podspecs need to be cleaned before the resolution step
|
75
|
+
# otherwise the sandbox might return an old podspec and not download
|
76
|
+
# the new one from an external source.
|
77
|
+
# - The resolver might trigger the download of Pods from external sources
|
78
|
+
# necessary to retrieve their podspec (unless it is instructed not to
|
79
|
+
# do it).
|
80
|
+
#
|
81
|
+
# @return [void]
|
82
|
+
#
|
83
|
+
def install!
|
84
|
+
resolve_dependencies
|
85
|
+
download_dependencies
|
86
|
+
generate_pods_project
|
87
|
+
integrate_user_project if config.integrate_targets?
|
88
|
+
end
|
11
89
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
90
|
+
def resolve_dependencies
|
91
|
+
UI.section "Analyzing dependencies" do
|
92
|
+
analyze
|
93
|
+
prepare_for_legacy_compatibility
|
94
|
+
clean_sandbox
|
95
|
+
end
|
16
96
|
end
|
17
97
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
pods.each { |p| p.link_headers }
|
24
|
-
@project
|
98
|
+
def download_dependencies
|
99
|
+
UI.section "Downloading dependencies" do
|
100
|
+
create_file_accessors
|
101
|
+
install_pod_sources
|
102
|
+
end
|
25
103
|
end
|
26
104
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
105
|
+
def generate_pods_project
|
106
|
+
UI.section "Generating Pods project" do
|
107
|
+
prepare_pods_project
|
108
|
+
run_pre_install_hooks
|
109
|
+
install_file_references
|
110
|
+
install_targets
|
111
|
+
run_post_install_hooks
|
112
|
+
write_pod_project
|
113
|
+
write_lockfiles
|
114
|
+
end
|
31
115
|
end
|
32
116
|
|
33
|
-
|
34
|
-
|
35
|
-
|
117
|
+
#-------------------------------------------------------------------------#
|
118
|
+
|
119
|
+
public
|
120
|
+
|
121
|
+
# @!group Installation results
|
122
|
+
|
123
|
+
# @return [Analyzer] the analyzer which provides the information about what
|
124
|
+
# needs to be installed.
|
125
|
+
#
|
126
|
+
attr_reader :analysis_result
|
127
|
+
|
128
|
+
# @return [Pod::Project] the `Pods/Pods.xcodeproj` project.
|
129
|
+
#
|
130
|
+
attr_reader :pods_project
|
131
|
+
|
132
|
+
# @return [Array<String>] The Pods that should be installed.
|
133
|
+
#
|
134
|
+
attr_reader :names_of_pods_to_install
|
135
|
+
|
136
|
+
# @return [Array<Library>] The libraries generated by the installation
|
137
|
+
# process.
|
138
|
+
#
|
139
|
+
attr_reader :libraries
|
140
|
+
|
141
|
+
# @return [Array<Specification>] The specifications that where installed.
|
142
|
+
#
|
143
|
+
attr_accessor :installed_specs
|
144
|
+
|
145
|
+
#-------------------------------------------------------------------------#
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
# @!group Installation steps
|
150
|
+
|
151
|
+
# @return [void]
|
152
|
+
#
|
153
|
+
def analyze
|
154
|
+
analyzer = Analyzer.new(sandbox, podfile, lockfile)
|
155
|
+
analyzer.update_mode = update_mode
|
156
|
+
@analysis_result = analyzer.analyze
|
157
|
+
@libraries = analyzer.result.libraries
|
158
|
+
end
|
159
|
+
|
160
|
+
# Prepares the Pods folder in order to be compatible with the most recent
|
161
|
+
# version of CocoaPods.
|
36
162
|
#
|
37
163
|
# @return [void]
|
38
164
|
#
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
165
|
+
def prepare_for_legacy_compatibility
|
166
|
+
# move_target_support_files_if_needed
|
167
|
+
# move_Local_Podspecs_to_Podspecs_if_needed
|
168
|
+
# move_pods_to_sources_folder_if_needed
|
169
|
+
end
|
170
|
+
|
171
|
+
# @return [void] In this step we clean all the folders that will be
|
172
|
+
# regenerated from scratch and any file which might not be
|
173
|
+
# overwritten.
|
174
|
+
#
|
175
|
+
# @todo [#247] Clean the headers of only the pods to install.
|
176
|
+
#
|
177
|
+
def clean_sandbox
|
178
|
+
sandbox.build_headers.implode!
|
179
|
+
sandbox.public_headers.implode!
|
180
|
+
|
181
|
+
unless sandbox_state.deleted.empty?
|
182
|
+
title_options = { :verbose_prefix => "-> ".red }
|
183
|
+
sandbox_state.deleted.each do |pod_name|
|
184
|
+
UI.titled_section("Removing #{pod_name}".red, title_options) do
|
185
|
+
sandbox.clean_pod(pod_name)
|
54
186
|
end
|
55
|
-
else
|
56
|
-
UI.section("Using #{pod}", "-> ".green)
|
57
187
|
end
|
58
188
|
end
|
59
189
|
end
|
60
190
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
191
|
+
# TODO: the file accessor should be initialized by the sandbox as they
|
192
|
+
# created by the Pod source installer as well.
|
193
|
+
#
|
194
|
+
def create_file_accessors
|
195
|
+
libraries.each do |library|
|
196
|
+
library.specs.each do |spec|
|
197
|
+
pod_root = sandbox.pod_dir(spec.root.name)
|
198
|
+
path_list = Sandbox::PathList.new(pod_root)
|
199
|
+
file_accessor = Sandbox::FileAccessor.new(path_list, spec.consumer(library.platform))
|
200
|
+
library.file_accessors ||= []
|
201
|
+
library.file_accessors << file_accessor
|
69
202
|
end
|
70
|
-
else
|
71
|
-
downloader.download
|
72
203
|
end
|
73
|
-
pod.downloaded = true
|
74
204
|
end
|
75
205
|
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
206
|
+
# Downloads, installs the documentation and cleans the sources of the Pods
|
207
|
+
# which need to be installed.
|
208
|
+
#
|
209
|
+
# @return [void]
|
210
|
+
#
|
211
|
+
def install_pod_sources
|
212
|
+
@installed_specs = []
|
213
|
+
pods_to_install = sandbox_state.added | sandbox_state.changed
|
214
|
+
title_options = { :verbose_prefix => "-> ".green }
|
215
|
+
root_specs.sort_by(&:name).each do |spec|
|
216
|
+
if pods_to_install.include?(spec.name)
|
217
|
+
UI.titled_section("Installing #{spec}".green, title_options) do
|
218
|
+
install_source_of_pod(spec.name)
|
219
|
+
end
|
220
|
+
else
|
221
|
+
UI.titled_section("Using #{spec}", title_options)
|
222
|
+
end
|
84
223
|
end
|
85
224
|
end
|
86
225
|
|
87
|
-
#
|
226
|
+
# Install the Pods. If the resolver indicated that a Pod should be
|
227
|
+
# installed and it exits, it is removed an then reinstalled. In any case if
|
228
|
+
# the Pod doesn't exits it is installed.
|
88
229
|
#
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
230
|
+
# @return [void]
|
231
|
+
#
|
232
|
+
def install_source_of_pod(pod_name)
|
233
|
+
specs_by_platform = {}
|
234
|
+
libraries.each do |library|
|
235
|
+
specs = library.specs.select { |spec| spec.root.name == pod_name }
|
236
|
+
|
237
|
+
unless specs.empty?
|
238
|
+
specs_by_platform[library.platform] ||= []
|
239
|
+
specs_by_platform[library.platform].concat(specs)
|
94
240
|
end
|
95
241
|
end
|
242
|
+
|
243
|
+
pod_installer = PodSourceInstaller.new(sandbox, specs_by_platform)
|
244
|
+
pod_installer.clean = config.clean?
|
245
|
+
pod_installer.aggressive_cache = config.aggressive_cache?
|
246
|
+
pod_installer.generate_docs = config.generate_docs?
|
247
|
+
pod_installer.install_docs = config.install_docs?
|
248
|
+
pod_installer.install!
|
249
|
+
@installed_specs.concat(specs_by_platform.values.flatten)
|
96
250
|
end
|
97
251
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
252
|
+
# Creates the Pods project from scratch if it doesn't exists.
|
253
|
+
#
|
254
|
+
# @return [void]
|
255
|
+
#
|
256
|
+
# @todo Clean and modify the project if it exists.
|
257
|
+
#
|
258
|
+
def prepare_pods_project
|
259
|
+
UI.message "- Creating Pods project" do
|
260
|
+
@pods_project = Pod::Project.new(sandbox.project_path)
|
261
|
+
if config.podfile_path.exist?
|
262
|
+
@pods_project.add_podfile(config.podfile_path)
|
263
|
+
end
|
264
|
+
sandbox.project = @pods_project
|
102
265
|
end
|
266
|
+
end
|
103
267
|
|
104
|
-
UI.section "Removing deleted dependencies" do
|
105
|
-
remove_deleted_dependencies!
|
106
|
-
end unless resolver.removed_pods.empty?
|
107
|
-
|
108
|
-
UI.section "Downloading dependencies" do
|
109
|
-
install_dependencies!
|
110
|
-
end
|
111
268
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
269
|
+
# Installs the file references in the Pods project. This is done once per
|
270
|
+
# Pod as the same file reference might be shared by multiple targets.
|
271
|
+
#
|
272
|
+
# @return [void]
|
273
|
+
#
|
274
|
+
def install_file_references
|
275
|
+
installer = FileReferencesInstaller.new(sandbox, libraries, pods_project)
|
276
|
+
installer.install!
|
277
|
+
end
|
116
278
|
|
117
|
-
|
118
|
-
|
279
|
+
# Installs the targets of the Pods projects and generates their support
|
280
|
+
# files.
|
281
|
+
#
|
282
|
+
# @return [void]
|
283
|
+
#
|
284
|
+
def install_targets
|
285
|
+
UI.message"- Installing targets" do
|
286
|
+
libraries.sort_by(&:name).each do |library|
|
287
|
+
next if library.target_definition.empty?
|
288
|
+
target_installer = TargetInstaller.new(sandbox, library)
|
289
|
+
target_installer.install!
|
119
290
|
end
|
291
|
+
end
|
292
|
+
end
|
120
293
|
|
121
|
-
|
122
|
-
|
123
|
-
|
294
|
+
# Writes the Pods project to the disk.
|
295
|
+
#
|
296
|
+
# @return [void]
|
297
|
+
#
|
298
|
+
def write_pod_project
|
299
|
+
UI.message "- Writing Xcode project file to #{UI.path sandbox.project_path}" do
|
300
|
+
pods_project.main_group.sort_by_type!
|
301
|
+
pods_project['Frameworks'].sort_by_type!
|
302
|
+
pods_project.save_as(sandbox.project_path)
|
303
|
+
end
|
304
|
+
end
|
124
305
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
306
|
+
# Writes the Podfile and the lock files.
|
307
|
+
#
|
308
|
+
# @todo Pass the checkout options to the Lockfile.
|
309
|
+
#
|
310
|
+
# @return [void]
|
311
|
+
#
|
312
|
+
def write_lockfiles
|
313
|
+
# checkout_options = sandbox.checkout_options
|
314
|
+
@lockfile = Lockfile.generate(podfile, analysis_result.specifications)
|
129
315
|
|
130
|
-
|
131
|
-
|
132
|
-
|
316
|
+
UI.message "- Writing Lockfile in #{UI.path config.lockfile_path}" do
|
317
|
+
@lockfile.write_to_disk(config.lockfile_path)
|
318
|
+
end
|
133
319
|
|
134
|
-
|
135
|
-
|
136
|
-
@lockfile.write_to_disk(config.project_lockfile)
|
137
|
-
end
|
320
|
+
UI.message "- Writing Manifest in #{UI.path sandbox.manifest_path}" do
|
321
|
+
@lockfile.write_to_disk(sandbox.manifest_path)
|
138
322
|
end
|
323
|
+
end
|
139
324
|
|
140
|
-
|
325
|
+
# Integrates the user projects adding the dependencies on the CocoaPods
|
326
|
+
# libraries, setting them up to use the xcconfigs and performing other
|
327
|
+
# actions. This step is also responsible of creating the workspace if
|
328
|
+
# needed.
|
329
|
+
#
|
330
|
+
# @return [void]
|
331
|
+
#
|
332
|
+
# @todo [#397] The libraries should be cleaned and the re-added on every
|
333
|
+
# installation. Maybe a clean_user_project phase should be added.
|
334
|
+
# In any case it appears to be a good idea store target definition
|
335
|
+
# information in the lockfile.
|
336
|
+
#
|
337
|
+
def integrate_user_project
|
338
|
+
UI.section "Integrating client #{'project'.pluralize(libraries.map(&:user_project_path).uniq.count) }" do
|
339
|
+
installation_root = config.installation_root
|
340
|
+
integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, libraries)
|
341
|
+
integrator.integrate!
|
342
|
+
end
|
141
343
|
end
|
142
344
|
|
345
|
+
#-------------------------------------------------------------------------#
|
346
|
+
|
347
|
+
private
|
348
|
+
|
349
|
+
# @!group Hooks
|
350
|
+
|
351
|
+
# Runs the pre install hooks of the installed specs and of the Podfile.
|
352
|
+
#
|
353
|
+
# @return [void]
|
354
|
+
#
|
143
355
|
def run_pre_install_hooks
|
144
|
-
|
145
|
-
|
146
|
-
|
356
|
+
UI.message "- Running pre install hooks" do
|
357
|
+
installed_specs.each do |spec|
|
358
|
+
executed = false
|
359
|
+
libraries_using_spec(spec).each do |lib|
|
360
|
+
executed ||= spec.pre_install!(pod_rep(spec.root.name), library_rep(lib))
|
361
|
+
end
|
362
|
+
UI.message "- #{spec.name}" if executed
|
147
363
|
end
|
364
|
+
|
365
|
+
executed = @podfile.pre_install!(installer_rep)
|
366
|
+
UI.message "- Podfile" if executed
|
148
367
|
end
|
149
|
-
@podfile.pre_install!(self)
|
150
368
|
end
|
151
369
|
|
370
|
+
# Runs the post install hooks of the installed specs and of the Podfile.
|
371
|
+
#
|
372
|
+
# @note Post install hooks run _before_ saving of project, so that they
|
373
|
+
# can alter it before it is written to the disk.
|
374
|
+
#
|
375
|
+
# @return [void]
|
376
|
+
#
|
152
377
|
def run_post_install_hooks
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
378
|
+
UI.message "- Running post install hooks" do
|
379
|
+
installed_specs.each do |spec|
|
380
|
+
executed = false
|
381
|
+
libraries_using_spec(spec).each do |lib|
|
382
|
+
executed ||= spec.post_install!(library_rep(lib))
|
383
|
+
end
|
384
|
+
UI.message "- #{spec.name}" if executed
|
158
385
|
end
|
386
|
+
executed = @podfile.post_install!(installer_rep)
|
387
|
+
UI.message "- Podfile" if executed
|
159
388
|
end
|
160
|
-
@podfile.post_install!(self)
|
161
389
|
end
|
162
390
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
391
|
+
#-------------------------------------------------------------------------#
|
392
|
+
|
393
|
+
public
|
394
|
+
|
395
|
+
# @!group Hooks Data
|
396
|
+
|
397
|
+
# @return [InstallerRepresentation]
|
398
|
+
#
|
399
|
+
def installer_rep
|
400
|
+
Hooks::InstallerRepresentation.new(self)
|
172
401
|
end
|
173
402
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
403
|
+
# @return [PodRepresentation] The hook representation of a Pod.
|
404
|
+
#
|
405
|
+
# @param [String] pod
|
406
|
+
# The name of the pod.
|
407
|
+
#
|
408
|
+
# @return [PodRepresentation] The pod representation.
|
409
|
+
#
|
410
|
+
def pod_rep(pod)
|
411
|
+
all_file_accessors = libraries.map(&:file_accessors).flatten.compact
|
412
|
+
file_accessors = all_file_accessors.select { |fa| fa.spec.root.name == pod }
|
413
|
+
Hooks::PodRepresentation.new(pod, file_accessors)
|
414
|
+
end
|
180
415
|
|
181
|
-
|
182
|
-
|
416
|
+
# @return [LibraryRepresentation]
|
417
|
+
#
|
418
|
+
def library_rep(library)
|
419
|
+
Hooks::LibraryRepresentation.new(sandbox, library)
|
183
420
|
end
|
184
421
|
|
185
|
-
|
186
|
-
|
422
|
+
# @return [Array<LibraryRepresentation>]
|
423
|
+
#
|
424
|
+
def library_reps
|
425
|
+
@library_reps ||= libraries.map { |lib| library_rep(lib) }
|
187
426
|
end
|
188
427
|
|
189
|
-
# @return [Array<
|
190
|
-
|
191
|
-
|
428
|
+
# @return [Array<PodRepresentation>]
|
429
|
+
#
|
430
|
+
def pod_reps
|
431
|
+
root_specs.sort_by { |spec| spec.name }.map { |spec| pod_rep(spec.name) }
|
192
432
|
end
|
193
433
|
|
194
|
-
#
|
195
|
-
#
|
196
|
-
|
197
|
-
|
434
|
+
# Returns the libraries which use the given specification.
|
435
|
+
#
|
436
|
+
# @param [Specification] spec
|
437
|
+
# The specification for which the client libraries are needed.
|
438
|
+
#
|
439
|
+
# @return [Array<Library>] The library.
|
440
|
+
#
|
441
|
+
def libraries_using_spec(spec)
|
442
|
+
libraries.select { |lib| lib.specs.include?(spec) }
|
198
443
|
end
|
199
444
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
445
|
+
#-------------------------------------------------------------------------#
|
446
|
+
|
447
|
+
private
|
448
|
+
|
449
|
+
# @!group Private helpers
|
450
|
+
|
451
|
+
# @return [Array<Specification>] All the root specifications of the
|
452
|
+
# installation.
|
453
|
+
#
|
454
|
+
def root_specs
|
455
|
+
analysis_result.specifications.map { |spec| spec.root }.uniq
|
456
|
+
end
|
457
|
+
|
458
|
+
# @return [SpecsState] The state of the sandbox returned by the analyzer.
|
459
|
+
#
|
460
|
+
def sandbox_state
|
461
|
+
analysis_result.sandbox_state
|
214
462
|
end
|
463
|
+
|
464
|
+
#-------------------------------------------------------------------------#
|
465
|
+
|
215
466
|
end
|
216
467
|
end
|