cocoapods 0.16.4 → 0.17.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|