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
data/lib/cocoapods/resolver.rb
CHANGED
@@ -1,221 +1,208 @@
|
|
1
|
-
require 'colored'
|
2
|
-
|
3
1
|
module Pod
|
4
|
-
class Resolver
|
5
|
-
include Config::Mixin
|
6
|
-
|
7
|
-
# @return [Bool] Whether the resolver should find the pods to install or
|
8
|
-
# the pods to update.
|
9
|
-
#
|
10
|
-
attr_accessor :update_mode
|
11
|
-
|
12
|
-
# @return [Bool] Whether the resolver should update the external specs
|
13
|
-
# in the resolution process.
|
14
|
-
#
|
15
|
-
attr_accessor :update_external_specs
|
16
|
-
|
17
|
-
# @return [Podfile] The Podfile used by the resolver.
|
18
|
-
#
|
19
|
-
attr_reader :podfile
|
20
2
|
|
21
|
-
|
22
|
-
|
23
|
-
|
3
|
+
# The resolver is responsible of generating a list of specifications grouped
|
4
|
+
# by target for a given Podfile.
|
5
|
+
#
|
6
|
+
# @todo Its current implementation is naive, in the sense that it can't do full
|
7
|
+
# automatic resolves like Bundler:
|
8
|
+
# [how-does-bundler-bundle](http://patshaughnessy.net/2011/9/24/how-does-bundler-bundle)
|
9
|
+
#
|
10
|
+
# @todo Another limitation is that the order of the dependencies matter. The
|
11
|
+
# current implementation could create issues, for example, if a
|
12
|
+
# specification is loaded for a target definition and later for another
|
13
|
+
# target is set in head mode. The first specification will not be in head
|
14
|
+
# mode.
|
15
|
+
#
|
16
|
+
#
|
17
|
+
class Resolver
|
24
18
|
|
25
|
-
# @return [Sandbox]
|
26
|
-
#
|
19
|
+
# @return [Sandbox] the Sandbox used by the resolver to find external
|
20
|
+
# dependencies.
|
27
21
|
#
|
28
22
|
attr_reader :sandbox
|
29
23
|
|
30
|
-
# @return [
|
31
|
-
# external source.
|
24
|
+
# @return [Podfile] the Podfile used by the resolver.
|
32
25
|
#
|
33
|
-
attr_reader :
|
26
|
+
attr_reader :podfile
|
34
27
|
|
35
|
-
# @return [Array<
|
28
|
+
# @return [Array<Dependency>] the list of dependencies locked to a specific
|
29
|
+
# version.
|
36
30
|
#
|
37
|
-
attr_reader :
|
31
|
+
attr_reader :locked_dependencies
|
38
32
|
|
39
|
-
# @
|
40
|
-
#
|
33
|
+
# @param [Sandbox] sandbox @see sandbox
|
34
|
+
# @param [Podfile] podfile @see podfile
|
35
|
+
# @param [Array<Dependency>] locked_dependencies @see locked_dependencies
|
41
36
|
#
|
42
|
-
|
37
|
+
def initialize(sandbox, podfile, locked_dependencies = [])
|
38
|
+
@sandbox = sandbox
|
39
|
+
@podfile = podfile
|
40
|
+
@locked_dependencies = locked_dependencies
|
41
|
+
end
|
43
42
|
|
44
|
-
|
45
|
-
# Returns the resolved specifications grouped by target.
|
46
|
-
#
|
47
|
-
attr_reader :specs_by_target
|
43
|
+
#-------------------------------------------------------------------------#
|
48
44
|
|
49
|
-
|
50
|
-
@podfile = podfile
|
51
|
-
@lockfile = lockfile
|
52
|
-
@sandbox = sandbox
|
53
|
-
@update_external_specs = true
|
45
|
+
public
|
54
46
|
|
55
|
-
|
56
|
-
@cached_sources = Source::Aggregate.new
|
57
|
-
end
|
47
|
+
# @!group Resolution
|
58
48
|
|
59
|
-
# Identifies the specifications that should be installed
|
60
|
-
# the resolver is in update mode or not.
|
49
|
+
# Identifies the specifications that should be installed.
|
61
50
|
#
|
62
|
-
# @return [Hash{
|
51
|
+
# @return [Hash{TargetDefinition => Array<Specification>}] specs_by_target
|
52
|
+
# the specifications that need to be installed grouped by target
|
53
|
+
# definition.
|
63
54
|
#
|
64
55
|
def resolve
|
65
|
-
@
|
56
|
+
@cached_sources = SourcesManager.aggregate
|
57
|
+
@cached_sets = {}
|
58
|
+
@cached_specs = {}
|
66
59
|
@specs_by_target = {}
|
67
|
-
@pods_from_external_sources = []
|
68
|
-
@pods_to_lock = []
|
69
|
-
|
70
|
-
if @lockfile
|
71
|
-
@pods_by_state = @lockfile.detect_changes_with_podfile(podfile)
|
72
|
-
UI.section "Finding added, modified or removed dependencies:" do
|
73
|
-
marks = {:added => "A".green, :changed => "M".yellow, :removed => "R".red, :unchanged => "-" }
|
74
|
-
@pods_by_state.each do |symbol, pod_names|
|
75
|
-
pod_names.each do |pod_name|
|
76
|
-
UI.message("#{marks[symbol]} #{pod_name}", '',2)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end if config.verbose?
|
80
|
-
@pods_to_lock = (lockfile.pods_names - @pods_by_state[:added] - @pods_by_state[:changed] - @pods_by_state[:removed]).uniq
|
81
|
-
end
|
82
|
-
|
83
|
-
unless config.skip_repo_update?
|
84
|
-
UI.section 'Updating spec repositories' do
|
85
|
-
Command::Repo.new(Command::ARGV.new(["update"])).run
|
86
|
-
end if !@lockfile || !(@pods_by_state[:added] + @pods_by_state[:changed]).empty? || update_mode
|
87
|
-
end
|
88
60
|
|
89
|
-
|
90
|
-
|
61
|
+
target_definitions = podfile.target_definitions.values.sort_by{ |td| td.name.to_s }
|
62
|
+
target_definitions.each do |target|
|
63
|
+
UI.section "Resolving dependencies for target `#{target.name}' (#{target.platform})" do
|
91
64
|
@loaded_specs = []
|
92
|
-
find_dependency_specs(
|
93
|
-
|
65
|
+
find_dependency_specs(podfile, target.dependencies, target)
|
66
|
+
specs = cached_specs.values_at(*@loaded_specs).sort_by(&:name)
|
67
|
+
specs_by_target[target] = specs
|
94
68
|
end
|
95
69
|
end
|
96
70
|
|
97
|
-
|
98
|
-
|
71
|
+
cached_specs.values.sort_by(&:name)
|
72
|
+
specs_by_target
|
99
73
|
end
|
100
74
|
|
101
|
-
# @return [Array<Specification>]
|
75
|
+
# @return [Hash{Podfile::TargetDefinition => Array<Specification>}]
|
76
|
+
# returns the resolved specifications grouped by target.
|
102
77
|
#
|
103
|
-
|
104
|
-
|
105
|
-
|
78
|
+
# @note The returned specifications can be subspecs.
|
79
|
+
#
|
80
|
+
attr_reader :specs_by_target
|
106
81
|
|
107
|
-
|
82
|
+
#-------------------------------------------------------------------------#
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# !@ Resolution context
|
87
|
+
|
88
|
+
# @return [Source::Aggregate] A cache of the sources needed to find the
|
89
|
+
# podspecs.
|
108
90
|
#
|
109
|
-
|
110
|
-
|
111
|
-
|
91
|
+
# @note The sources are cached because frequently accessed by the
|
92
|
+
# resolver and loading them requires disk activity.
|
93
|
+
#
|
94
|
+
attr_accessor :cached_sources
|
112
95
|
|
113
|
-
# @return [
|
114
|
-
#
|
115
|
-
#
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
@pods_to_install += specs.select do |spec|
|
124
|
-
spec.version.head? || pods_from_external_sources.include?(spec.pod_name)
|
125
|
-
end.map(&:name)
|
126
|
-
end
|
127
|
-
@pods_to_install += @pods_by_state[:added] + @pods_by_state[:changed]
|
128
|
-
else
|
129
|
-
@pods_to_install = specs.map(&:name)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
@pods_to_install
|
133
|
-
end
|
96
|
+
# @return [Hash<String => Set>] A cache that keeps tracks of the sets
|
97
|
+
# loaded by the resolution process.
|
98
|
+
#
|
99
|
+
# @note Sets store the resolved dependencies and return the highest
|
100
|
+
# available specification found in the sources. This is done
|
101
|
+
# globally and not per target definition because there can be just
|
102
|
+
# one Pod installation, so different version of the same Pods for
|
103
|
+
# target definitions are not allowed.
|
104
|
+
#
|
105
|
+
attr_accessor :cached_sets
|
134
106
|
|
135
|
-
# @return [
|
136
|
-
#
|
137
|
-
# stripped from subspecs.
|
107
|
+
# @return [Hash<String => Specification>] The loaded specifications grouped
|
108
|
+
# by name.
|
138
109
|
#
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
previously_installed = lockfile.pods_names.map { |pod_name| pod_name.split('/').first }
|
143
|
-
installed = specs.map { |spec| spec.name.split('/').first }
|
144
|
-
@removed_pods = previously_installed - installed
|
145
|
-
end
|
146
|
-
@removed_pods
|
147
|
-
end
|
110
|
+
attr_accessor :cached_specs
|
111
|
+
|
112
|
+
#-------------------------------------------------------------------------#
|
148
113
|
|
149
114
|
private
|
150
115
|
|
151
|
-
#
|
152
|
-
#
|
153
|
-
def find_cached_set(dependency, platform)
|
154
|
-
set_name = dependency.name.split('/').first
|
155
|
-
@cached_sets[set_name] ||= begin
|
156
|
-
if dependency.specification
|
157
|
-
Specification::Set::External.new(dependency.specification)
|
158
|
-
elsif external_source = dependency.external_source
|
159
|
-
if update_mode && update_external_specs
|
160
|
-
# Always update external sources in update mode.
|
161
|
-
specification = external_source.specification_from_external(@sandbox, platform)
|
162
|
-
else
|
163
|
-
# Don't update external sources in install mode if not needed.
|
164
|
-
specification = external_source.specification_from_sandbox(@sandbox, platform)
|
165
|
-
end
|
166
|
-
set = Specification::Set::External.new(specification)
|
167
|
-
if dependency.subspec_dependency?
|
168
|
-
@cached_sets[dependency.top_level_spec_name] ||= set
|
169
|
-
end
|
170
|
-
set
|
171
|
-
else
|
172
|
-
@cached_sources.search(dependency)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
116
|
+
# @!group Private helpers
|
176
117
|
|
177
|
-
# Resolves the dependencies of a specification and stores them
|
118
|
+
# Resolves recursively the dependencies of a specification and stores them
|
119
|
+
# in the @cached_specs ivar.
|
120
|
+
#
|
121
|
+
# @param [Podfile, Specification, #to_s] dependent_spec
|
122
|
+
# the specification whose dependencies are being resolved. Used
|
123
|
+
# only for UI purposes.
|
124
|
+
#
|
125
|
+
# @param [Array<Dependency>] dependencies
|
126
|
+
# the dependencies of the specification.
|
178
127
|
#
|
179
|
-
# @param
|
180
|
-
#
|
181
|
-
#
|
128
|
+
# @param [TargetDefinition] target_definition
|
129
|
+
# the target definition that owns the specification.
|
130
|
+
#
|
131
|
+
# @note If there is a locked dependency with the same name of a
|
132
|
+
# given dependency the locked one is used in place of the
|
133
|
+
# dependency of the specification. In this way it is possible to
|
134
|
+
# prevent the update of the version of installed pods not changed
|
135
|
+
# in the Podfile.
|
136
|
+
#
|
137
|
+
# @note The recursive process checks if a dependency has already been
|
138
|
+
# loaded to prevent an infinite loop.
|
139
|
+
#
|
140
|
+
# @note The set class merges all (of all the target definitions) the
|
141
|
+
# dependencies and thus it keeps track of whether it is in head
|
142
|
+
# mode or from an external source because {Dependency#merge}
|
143
|
+
# preserves this information.
|
182
144
|
#
|
183
145
|
# @return [void]
|
184
146
|
#
|
185
|
-
def find_dependency_specs(
|
147
|
+
def find_dependency_specs(dependent_spec, dependencies, target_definition)
|
186
148
|
dependencies.each do |dependency|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
end
|
149
|
+
locked_dep = locked_dependencies.find { |ld| ld.name == dependency.name }
|
150
|
+
dependency = locked_dep if locked_dep
|
151
|
+
|
191
152
|
UI.message("- #{dependency}", '', 2) do
|
192
|
-
set = find_cached_set(dependency
|
193
|
-
set.required_by(dependency,
|
153
|
+
set = find_cached_set(dependency)
|
154
|
+
set.required_by(dependency, dependent_spec.to_s)
|
194
155
|
|
195
|
-
# Ensure we don't resolve the same spec twice for one target
|
196
156
|
unless @loaded_specs.include?(dependency.name)
|
197
|
-
spec = set.
|
198
|
-
@pods_from_external_sources << spec.pod_name if dependency.external?
|
157
|
+
spec = set.specification.subspec_by_name(dependency.name)
|
199
158
|
@loaded_specs << spec.name
|
200
|
-
|
201
|
-
|
202
|
-
spec.activate_platform(target_definition.platform)
|
159
|
+
cached_specs[spec.name] = spec
|
160
|
+
validate_platform(spec, target_definition)
|
203
161
|
spec.version.head = dependency.head?
|
204
|
-
|
205
|
-
|
162
|
+
|
163
|
+
spec_dependencies = spec.all_dependencies(target_definition.platform)
|
164
|
+
find_dependency_specs(spec, spec_dependencies, target_definition)
|
206
165
|
end
|
207
|
-
validate_platform(spec || @cached_specs[dependency.name], target_definition)
|
208
166
|
end
|
209
167
|
end
|
210
168
|
end
|
211
169
|
|
212
|
-
#
|
170
|
+
# Loads or returns a previously initialized for the Pod of the given
|
171
|
+
# dependency.
|
172
|
+
#
|
173
|
+
# @param [Dependency] dependency
|
174
|
+
# the dependency for which the set is needed.
|
213
175
|
#
|
214
|
-
# @
|
176
|
+
# @return [Set] the cached set for a given dependency.
|
177
|
+
#
|
178
|
+
def find_cached_set(dependency)
|
179
|
+
name = dependency.root_name
|
180
|
+
unless cached_sets[name]
|
181
|
+
if dependency.external_source
|
182
|
+
spec = sandbox.specification(dependency.root_name)
|
183
|
+
unless spec
|
184
|
+
raise StandardError, "[Bug] Unable to find the specification for `#{dependency}`."
|
185
|
+
end
|
186
|
+
set = Specification::Set::External.new(spec)
|
187
|
+
else
|
188
|
+
set = cached_sources.search(dependency)
|
189
|
+
end
|
190
|
+
cached_sets[name] = set
|
191
|
+
end
|
192
|
+
cached_sets[name]
|
193
|
+
end
|
194
|
+
|
195
|
+
# Ensures that a specification is compatible with the platform of a target.
|
196
|
+
#
|
197
|
+
# @raise If the specification is not supported by the target.
|
198
|
+
#
|
199
|
+
# @return [void]
|
215
200
|
#
|
216
201
|
def validate_platform(spec, target)
|
217
|
-
unless spec.available_platforms.any? { |
|
218
|
-
raise Informative, "
|
202
|
+
unless spec.available_platforms.any? { |p| target.platform.supports?(p) }
|
203
|
+
raise Informative, "The platform of the target `#{target.name}` " \
|
204
|
+
"(#{target.platform}) is not compatible with `#{spec}` which has " \
|
205
|
+
"a minimum requirement of #{spec.available_platforms.join(' - ')}."
|
219
206
|
end
|
220
207
|
end
|
221
208
|
end
|
data/lib/cocoapods/sandbox.rb
CHANGED
@@ -1,105 +1,327 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
|
3
3
|
module Pod
|
4
|
+
|
5
|
+
# The sandbox provides support for the directory that CocoaPods uses for an
|
6
|
+
# installation. In this directory the Pods projects, the support files and
|
7
|
+
# the sources of the Pods are stored.
|
8
|
+
#
|
9
|
+
# CocoaPods assumes to have control of the sandbox.
|
10
|
+
#
|
11
|
+
# Once completed the sandbox will have the following file structure:
|
12
|
+
#
|
13
|
+
# Pods
|
14
|
+
# |
|
15
|
+
# +-- Headers
|
16
|
+
# | +-- Private
|
17
|
+
# | | +-- [Pod Name]
|
18
|
+
# | +-- Public
|
19
|
+
# | +-- [Pod Name]
|
20
|
+
# |
|
21
|
+
# +-- Sources
|
22
|
+
# | +-- [Pod Name]
|
23
|
+
# |
|
24
|
+
# +-- Specifications
|
25
|
+
# | +-- External Sources
|
26
|
+
# | +-- Normal Sources
|
27
|
+
# |
|
28
|
+
# +-- Target Support Files
|
29
|
+
# | +-- [Target Name]
|
30
|
+
# | +-- Acknowledgements.markdown
|
31
|
+
# | +-- Acknowledgements.plist
|
32
|
+
# | +-- Pods.xcconfig
|
33
|
+
# | +-- Pods-prefix.pch
|
34
|
+
# | +-- Pods-dummy_Pods.m
|
35
|
+
# |
|
36
|
+
# +-- Manifest.lock
|
37
|
+
# |
|
38
|
+
# +-- Pods.xcodeproj
|
39
|
+
#
|
4
40
|
class Sandbox
|
41
|
+
|
42
|
+
autoload :FileAccessor, 'cocoapods/sandbox/file_accessor'
|
43
|
+
autoload :HeadersStore, 'cocoapods/sandbox/headers_store'
|
44
|
+
autoload :PathList, 'cocoapods/sandbox/path_list'
|
45
|
+
|
46
|
+
# @return [Pathname] the root of the sandbox.
|
47
|
+
#
|
5
48
|
attr_reader :root
|
49
|
+
|
50
|
+
# @return [HeadersStore] the header directory for the Pods libraries.
|
51
|
+
#
|
6
52
|
attr_reader :build_headers
|
7
|
-
attr_reader :public_headers
|
8
53
|
|
9
|
-
|
10
|
-
|
54
|
+
# @return [HeadersStore] the header directory for the user targets.
|
55
|
+
#
|
56
|
+
attr_reader :public_headers
|
11
57
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
58
|
+
# @param [String, Pathname] root @see root
|
59
|
+
#
|
60
|
+
def initialize(root)
|
61
|
+
@root = Pathname.new(root)
|
62
|
+
@build_headers = HeadersStore.new(self, "BuildHeaders")
|
63
|
+
@public_headers = HeadersStore.new(self, "Headers")
|
64
|
+
@predownloaded_pods = []
|
65
|
+
@checkout_sources = {}
|
66
|
+
@local_pods = {}
|
18
67
|
FileUtils.mkdir_p(@root)
|
19
68
|
end
|
20
69
|
|
70
|
+
# @return [Lockfile] the manifest which contains the information about the
|
71
|
+
# installed pods.
|
72
|
+
#
|
73
|
+
def manifest
|
74
|
+
Lockfile.from_file(manifest_path) if manifest_path.exist?
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [Project] the Pods project.
|
78
|
+
#
|
79
|
+
attr_accessor :project
|
80
|
+
|
81
|
+
# Removes the sandbox.
|
82
|
+
#
|
83
|
+
# @return [void]
|
84
|
+
#
|
21
85
|
def implode
|
22
86
|
root.rmtree
|
23
87
|
end
|
24
88
|
|
89
|
+
#
|
90
|
+
#
|
91
|
+
#
|
92
|
+
def clean_pod(name)
|
93
|
+
root_name = Specification.root_name(name)
|
94
|
+
unless local?(root_name)
|
95
|
+
path = pod_dir(name)
|
96
|
+
path.rmtree if path.exist?
|
97
|
+
end
|
98
|
+
podspe_path = specification_path(name)
|
99
|
+
podspe_path.rmtree if podspe_path
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [String] a string representation suitable for debugging.
|
103
|
+
#
|
104
|
+
def inspect
|
105
|
+
"#<#{self.class}> with root #{root}"
|
106
|
+
end
|
107
|
+
|
108
|
+
#-------------------------------------------------------------------------#
|
109
|
+
|
110
|
+
public
|
111
|
+
|
112
|
+
# @!group Paths
|
113
|
+
|
114
|
+
# @return [Pathname] the path of the manifest.
|
115
|
+
#
|
116
|
+
def manifest_path
|
117
|
+
root + "Manifest.lock"
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [Pathname] the path of the Pods project.
|
121
|
+
#
|
25
122
|
def project_path
|
26
123
|
root + "Pods.xcodeproj"
|
27
124
|
end
|
28
125
|
|
29
|
-
|
30
|
-
|
31
|
-
|
126
|
+
# Returns the path for the directory where to store the support files of
|
127
|
+
# a target.
|
128
|
+
#
|
129
|
+
# @param [String] name
|
130
|
+
# The name of the target.
|
131
|
+
#
|
132
|
+
# @return [Pathname] the path of the support files.
|
133
|
+
#
|
134
|
+
def library_support_files_dir(name)
|
135
|
+
# root + "Target Support Files/#{name}"
|
136
|
+
root
|
32
137
|
end
|
33
138
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
139
|
+
# Returns the path where the Pod with the given name is stored, taking into
|
140
|
+
# account whether the Pod is locally sourced.
|
141
|
+
#
|
142
|
+
# @param [String] name
|
143
|
+
# The name of the Pod.
|
144
|
+
#
|
145
|
+
# @return [Pathname] the path of the Pod.
|
146
|
+
#
|
147
|
+
def pod_dir(name)
|
148
|
+
root_name = Specification.root_name(name)
|
149
|
+
if local?(root_name)
|
150
|
+
Pathname.new(local_pods[root_name])
|
151
|
+
else
|
152
|
+
# root + "Sources/#{name}"
|
153
|
+
root + root_name
|
38
154
|
end
|
39
155
|
end
|
40
156
|
|
41
|
-
|
157
|
+
#-------------------------------------------------------------------------#
|
158
|
+
|
159
|
+
public
|
160
|
+
|
161
|
+
# @!group Specification store
|
162
|
+
|
163
|
+
# Returns the specification for the Pod with the given name.
|
164
|
+
#
|
165
|
+
# @param [String] name
|
166
|
+
# the name of the Pod for which the specification is requested.
|
42
167
|
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
168
|
+
# @return [Specification] the specification if the file is found.
|
169
|
+
#
|
170
|
+
def specification(name)
|
171
|
+
if file = specification_path(name)
|
172
|
+
Specification.from_file(file)
|
47
173
|
end
|
48
174
|
end
|
49
175
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
176
|
+
# @return [Pathname] the path for the directory where to store the
|
177
|
+
# specifications.
|
178
|
+
#
|
179
|
+
# @todo Migrate old installations and store the for all the pods.
|
180
|
+
# Two folders should be created `External Sources` and `Podspecs`.
|
181
|
+
#
|
182
|
+
def specifications_dir(external_source = false)
|
183
|
+
# root + "Specifications"
|
184
|
+
root + "Local Podspecs"
|
55
185
|
end
|
56
186
|
|
57
|
-
|
58
|
-
|
187
|
+
# Returns the path of the specification for the Pod with the
|
188
|
+
# given name, if one is stored.
|
189
|
+
#
|
190
|
+
# @param [String] name
|
191
|
+
# the name of the Pod for which the podspec file is requested.
|
192
|
+
#
|
193
|
+
# @return [Pathname] the path or nil.
|
194
|
+
# @return [Nil] if the podspec is not stored.
|
195
|
+
#
|
196
|
+
def specification_path(name)
|
197
|
+
path = specifications_dir + "#{name}.podspec"
|
59
198
|
path.exist? ? path : nil
|
60
199
|
end
|
61
|
-
end
|
62
200
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
201
|
+
# Stores a specification in the `Local Podspecs` folder.
|
202
|
+
#
|
203
|
+
# @param [Sandbox] sandbox
|
204
|
+
# the sandbox where the podspec should be stored.
|
205
|
+
#
|
206
|
+
# @param [String, Pathname] podspec
|
207
|
+
# The contents of the specification (String) or the path to a
|
208
|
+
# podspec file (Pathname).
|
209
|
+
#
|
210
|
+
# @todo Store all the specifications (including those not originating
|
211
|
+
# from external sources) so users can check them.
|
212
|
+
#
|
213
|
+
def store_podspec(name, podspec, external_source = false)
|
214
|
+
output_path = specifications_dir(external_source) + "#{name}.podspec"
|
215
|
+
output_path.dirname.mkpath
|
216
|
+
if podspec.is_a?(String)
|
217
|
+
output_path.open('w') { |f| f.puts(podspec) }
|
218
|
+
else
|
219
|
+
unless podspec.exist?
|
220
|
+
raise Informative, "No podspec found for `#{name}` in #{podspec}"
|
221
|
+
end
|
222
|
+
FileUtils.copy(podspec, output_path)
|
223
|
+
end
|
224
|
+
spec = Specification.from_file(output_path)
|
225
|
+
unless spec.name == name
|
226
|
+
raise Informative, "The name of the given podspec `#{spec.name}` doesn't match the expected one `#{name}`"
|
227
|
+
end
|
68
228
|
end
|
69
229
|
|
70
|
-
|
71
|
-
|
72
|
-
|
230
|
+
#-------------------------------------------------------------------------#
|
231
|
+
|
232
|
+
public
|
233
|
+
|
234
|
+
# @!group Pods information
|
73
235
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
236
|
+
# Marks a Pod as pre-downloaded
|
237
|
+
#
|
238
|
+
# @param [String] name
|
239
|
+
# The name of the Pod.
|
240
|
+
#
|
241
|
+
# @return [void]
|
242
|
+
#
|
243
|
+
def store_pre_downloaded_pod(name)
|
244
|
+
root_name = Specification.root_name(name)
|
245
|
+
predownloaded_pods << root_name
|
81
246
|
end
|
82
247
|
|
83
|
-
|
84
|
-
|
248
|
+
# @return [Array<String>] The names of the pods that have been
|
249
|
+
# pre-downloaded from an external source.
|
250
|
+
#
|
251
|
+
attr_reader :predownloaded_pods
|
252
|
+
|
253
|
+
# Checks if a Pod has been pre-downloaded by the resolver in order to fetch
|
254
|
+
# the podspec.
|
255
|
+
#
|
256
|
+
# @param [String] name
|
257
|
+
# The name of the Pod.
|
258
|
+
#
|
259
|
+
# @return [Bool] Whether the Pod has been pre-downloaded.
|
260
|
+
#
|
261
|
+
def predownloaded?(name)
|
262
|
+
root_name = Specification.root_name(name)
|
263
|
+
predownloaded_pods.include?(root_name)
|
85
264
|
end
|
86
265
|
|
87
|
-
|
88
|
-
|
266
|
+
#--------------------------------------#
|
267
|
+
|
268
|
+
# Stores the local path of a Pod.
|
269
|
+
#
|
270
|
+
# @param [String] name
|
271
|
+
# The name of the Pod.
|
272
|
+
#
|
273
|
+
# @param [Hash] source
|
274
|
+
# The hash which contains the options as returned by the
|
275
|
+
# downloader.
|
276
|
+
#
|
277
|
+
# @return [void]
|
278
|
+
#
|
279
|
+
def store_checkout_source(name, source)
|
280
|
+
root_name = Specification.root_name(name)
|
281
|
+
checkout_sources[root_name] = source
|
89
282
|
end
|
90
283
|
|
91
|
-
#
|
284
|
+
# @return [Hash{String=>Hash}] The options necessary to recreate the exact
|
285
|
+
# checkout of a given Pod grouped by its name.
|
286
|
+
#
|
287
|
+
attr_reader :checkout_sources
|
288
|
+
|
289
|
+
#--------------------------------------#
|
290
|
+
|
291
|
+
# Stores the local path of a Pod.
|
292
|
+
#
|
293
|
+
# @param [String] name
|
294
|
+
# The name of the Pod.
|
92
295
|
#
|
93
|
-
# @param
|
296
|
+
# @param [#to_s] path
|
297
|
+
# The local path where the Pod is stored.
|
94
298
|
#
|
95
299
|
# @return [void]
|
96
300
|
#
|
97
|
-
def
|
98
|
-
|
301
|
+
def store_local_path(name, path)
|
302
|
+
root_name = Specification.root_name(name)
|
303
|
+
local_pods[root_name] = path.to_s
|
99
304
|
end
|
100
305
|
|
101
|
-
|
102
|
-
|
306
|
+
# @return [Hash{String=>String}] The path of the Pods with a local source
|
307
|
+
# grouped by their name.
|
308
|
+
#
|
309
|
+
attr_reader :local_pods
|
310
|
+
|
311
|
+
# Checks if a Pod is locally sourced?
|
312
|
+
#
|
313
|
+
# @param [String] name
|
314
|
+
# The name of the Pod.
|
315
|
+
#
|
316
|
+
# @return [Bool] Whether the Pod is locally sourced.
|
317
|
+
#
|
318
|
+
def local?(name)
|
319
|
+
root_name = Specification.root_name(name)
|
320
|
+
!local_pods[root_name].nil?
|
103
321
|
end
|
322
|
+
|
323
|
+
#-------------------------------------------------------------------------#
|
324
|
+
|
104
325
|
end
|
105
326
|
end
|
327
|
+
|