cocoapods-square-stable 0.19.3
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 +1296 -0
- data/LICENSE +20 -0
- data/README.md +94 -0
- data/bin/pod +16 -0
- data/bin/sandbox-pod +120 -0
- data/lib/cocoapods.rb +77 -0
- data/lib/cocoapods/command.rb +116 -0
- data/lib/cocoapods/command/help.rb +23 -0
- data/lib/cocoapods/command/inter_process_communication.rb +178 -0
- data/lib/cocoapods/command/list.rb +77 -0
- data/lib/cocoapods/command/outdated.rb +56 -0
- data/lib/cocoapods/command/podfile_info.rb +91 -0
- data/lib/cocoapods/command/project.rb +88 -0
- data/lib/cocoapods/command/push.rb +172 -0
- data/lib/cocoapods/command/repo.rb +145 -0
- data/lib/cocoapods/command/search.rb +61 -0
- data/lib/cocoapods/command/setup.rb +134 -0
- data/lib/cocoapods/command/spec.rb +590 -0
- data/lib/cocoapods/config.rb +231 -0
- data/lib/cocoapods/downloader.rb +59 -0
- data/lib/cocoapods/executable.rb +118 -0
- data/lib/cocoapods/external_sources.rb +363 -0
- data/lib/cocoapods/file_list.rb +36 -0
- data/lib/cocoapods/gem_version.rb +7 -0
- data/lib/cocoapods/generator/acknowledgements.rb +107 -0
- data/lib/cocoapods/generator/acknowledgements/markdown.rb +40 -0
- data/lib/cocoapods/generator/acknowledgements/plist.rb +64 -0
- data/lib/cocoapods/generator/bridge_support.rb +22 -0
- data/lib/cocoapods/generator/copy_resources_script.rb +54 -0
- data/lib/cocoapods/generator/dummy_source.rb +22 -0
- data/lib/cocoapods/generator/prefix_header.rb +82 -0
- data/lib/cocoapods/generator/target_environment_header.rb +86 -0
- data/lib/cocoapods/generator/xcconfig.rb +185 -0
- data/lib/cocoapods/hooks/installer_representation.rb +134 -0
- data/lib/cocoapods/hooks/library_representation.rb +94 -0
- data/lib/cocoapods/hooks/pod_representation.rb +74 -0
- data/lib/cocoapods/installer.rb +571 -0
- data/lib/cocoapods/installer/analyzer.rb +559 -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 +248 -0
- data/lib/cocoapods/installer/target_installer.rb +379 -0
- data/lib/cocoapods/installer/user_project_integrator.rb +180 -0
- data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +224 -0
- data/lib/cocoapods/library.rb +202 -0
- data/lib/cocoapods/open_uri.rb +24 -0
- data/lib/cocoapods/project.rb +209 -0
- data/lib/cocoapods/resolver.rb +212 -0
- data/lib/cocoapods/sandbox.rb +343 -0
- data/lib/cocoapods/sandbox/file_accessor.rb +217 -0
- data/lib/cocoapods/sandbox/headers_store.rb +96 -0
- data/lib/cocoapods/sandbox/path_list.rb +208 -0
- data/lib/cocoapods/sources_manager.rb +276 -0
- data/lib/cocoapods/user_interface.rb +304 -0
- data/lib/cocoapods/user_interface/error_report.rb +101 -0
- data/lib/cocoapods/validator.rb +350 -0
- metadata +238 -0
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
|
5
|
+
# The Pods project.
|
6
|
+
#
|
7
|
+
# Model class which provides helpers for working with the Pods project
|
8
|
+
# through the installation process.
|
9
|
+
#
|
10
|
+
class Project < Xcodeproj::Project
|
11
|
+
|
12
|
+
# @return [Pathname] the path of the xcodeproj file which stores the
|
13
|
+
# project.
|
14
|
+
#
|
15
|
+
attr_reader :path
|
16
|
+
|
17
|
+
# @param [Sandbox] sandbox @see #sandbox
|
18
|
+
#
|
19
|
+
def initialize(path = nil)
|
20
|
+
super(nil) # Recreate the project from scratch for now.
|
21
|
+
@path = path
|
22
|
+
@support_files_group = new_group('Targets Support Files')
|
23
|
+
|
24
|
+
@refs_by_absolute_path = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Pathname] the path of the xcodeproj file which stores the
|
28
|
+
# project.
|
29
|
+
#
|
30
|
+
attr_reader :path
|
31
|
+
|
32
|
+
# @return [Pathname] the directory where the project is stored.
|
33
|
+
#
|
34
|
+
def root
|
35
|
+
@root ||= path.dirname
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [Pathname] Returns the relative path from the project root.
|
39
|
+
#
|
40
|
+
# @param [Pathname] path
|
41
|
+
# The path that needs to be converted to the relative format.
|
42
|
+
#
|
43
|
+
# @note If the two absolute paths don't share the same root directory an
|
44
|
+
# extra `../` is added to the result of
|
45
|
+
# {Pathname#relative_path_from}.
|
46
|
+
#
|
47
|
+
# @example
|
48
|
+
#
|
49
|
+
# path = Pathname.new('/Users/dir')
|
50
|
+
# @sandbox.root #=> Pathname('/tmp/CocoaPods/Lint/Pods')
|
51
|
+
#
|
52
|
+
# @sandbox.relativize(path) #=> '../../../../Users/dir'
|
53
|
+
# @sandbox.relativize(path) #=> '../../../../../Users/dir'
|
54
|
+
#
|
55
|
+
def relativize(path)
|
56
|
+
unless path.absolute?
|
57
|
+
raise StandardError, "[Bug] Attempt to add relative path `#{path}` to the Pods project"
|
58
|
+
end
|
59
|
+
|
60
|
+
result = path.relative_path_from(root)
|
61
|
+
unless root.to_s.split('/')[1] == path.to_s.split('/')[1]
|
62
|
+
result = Pathname.new('../') + result
|
63
|
+
end
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [String] a string representation suited for debugging.
|
68
|
+
#
|
69
|
+
def inspect
|
70
|
+
"#<#{self.class}> path:#{path}"
|
71
|
+
end
|
72
|
+
|
73
|
+
#-------------------------------------------------------------------------#
|
74
|
+
|
75
|
+
public
|
76
|
+
|
77
|
+
# @!group Groups
|
78
|
+
|
79
|
+
# @return [PBXGroup] the group where the support files for the Pod
|
80
|
+
# libraries should be added.
|
81
|
+
#
|
82
|
+
attr_reader :support_files_group
|
83
|
+
|
84
|
+
# Returns the `Pods` group, creating it if needed.
|
85
|
+
#
|
86
|
+
# @return [PBXGroup] the group.
|
87
|
+
#
|
88
|
+
def pods
|
89
|
+
@pods ||= new_group('Pods')
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns the `Local Pods` group, creating it if needed. This group is used
|
93
|
+
# to contain locally sourced pods.
|
94
|
+
#
|
95
|
+
# @return [PBXGroup] the group.
|
96
|
+
#
|
97
|
+
def local_pods
|
98
|
+
@local_pods ||= new_group('Local Pods')
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns the `Local Pods` group, creating it if needed. This group is used
|
102
|
+
# to contain locally sourced pods.
|
103
|
+
#
|
104
|
+
# @return [PBXGroup] the group.
|
105
|
+
#
|
106
|
+
def resources
|
107
|
+
@resources ||= new_group('Resources')
|
108
|
+
end
|
109
|
+
|
110
|
+
# Adds a group as child to the `Pods` group namespacing subspecs.
|
111
|
+
#
|
112
|
+
# @param [String] spec_name
|
113
|
+
# The full name of the specification.
|
114
|
+
#
|
115
|
+
# @param [PBXGroup] root_group
|
116
|
+
# The group where to add the specification. Either `Pods` or `Local
|
117
|
+
# Pods`.
|
118
|
+
#
|
119
|
+
# @return [PBXGroup] the group for the spec with the given name.
|
120
|
+
#
|
121
|
+
def add_spec_group(spec_name, root_group)
|
122
|
+
current_group = root_group
|
123
|
+
group = nil
|
124
|
+
spec_name.split('/').each do |name|
|
125
|
+
group = current_group[name] || current_group.new_group(name)
|
126
|
+
current_group = group
|
127
|
+
end
|
128
|
+
group
|
129
|
+
end
|
130
|
+
|
131
|
+
#-------------------------------------------------------------------------#
|
132
|
+
|
133
|
+
public
|
134
|
+
|
135
|
+
# @!group File references
|
136
|
+
|
137
|
+
# Adds a file reference for each one of the given files in the specified
|
138
|
+
# group, namespaced by specification unless a file reference for the given
|
139
|
+
# path already exits.
|
140
|
+
#
|
141
|
+
# @note With this set-up different subspecs might not reference the same
|
142
|
+
# file (i.e. the first will win). Not sure thought if this is a
|
143
|
+
# limitation or a feature.
|
144
|
+
#
|
145
|
+
# @param [Array<Pathname,String>] paths
|
146
|
+
# The files for which the file reference is needed.
|
147
|
+
#
|
148
|
+
# @param [String] spec_name
|
149
|
+
# The full name of the specification.
|
150
|
+
#
|
151
|
+
# @param [PBXGroup] parent_group
|
152
|
+
# The group where the file references should be added.
|
153
|
+
#
|
154
|
+
# @return [void]
|
155
|
+
#
|
156
|
+
def add_file_references(absolute_path, spec_name, parent_group)
|
157
|
+
group = add_spec_group(spec_name, parent_group)
|
158
|
+
absolute_path.each do |file|
|
159
|
+
existing = file_reference(file)
|
160
|
+
unless existing
|
161
|
+
file = Pathname.new(file)
|
162
|
+
ref = group.new_file(relativize(file))
|
163
|
+
@refs_by_absolute_path[file] = ref
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Returns the file reference for the given absolute file path.
|
169
|
+
#
|
170
|
+
# @param [Pathname,String] absolute_path
|
171
|
+
# The absolute path of the file whose reference is needed.
|
172
|
+
#
|
173
|
+
# @return [PBXFileReference] The file reference.
|
174
|
+
# @return [Nil] If no file reference could be found.
|
175
|
+
#
|
176
|
+
def file_reference(absolute_path)
|
177
|
+
absolute_path = Pathname.new(absolute_path)
|
178
|
+
refs_by_absolute_path[absolute_path]
|
179
|
+
end
|
180
|
+
|
181
|
+
# Adds a file reference to the podfile.
|
182
|
+
#
|
183
|
+
# @param [Pathname,String] podfile_path
|
184
|
+
# the path of the podfile
|
185
|
+
#
|
186
|
+
# @return [PBXFileReference] the file reference.
|
187
|
+
#
|
188
|
+
def add_podfile(podfile_path)
|
189
|
+
podfile_path = Pathname.new(podfile_path)
|
190
|
+
podfile_ref = new_file(relativize(podfile_path))
|
191
|
+
podfile_ref.xc_language_specification_identifier = 'xcode.lang.ruby'
|
192
|
+
podfile_ref
|
193
|
+
end
|
194
|
+
|
195
|
+
#-------------------------------------------------------------------------#
|
196
|
+
|
197
|
+
private
|
198
|
+
|
199
|
+
# @!group Private helpers
|
200
|
+
|
201
|
+
# @return [Hash{Pathname => PBXFileReference}] The file references grouped
|
202
|
+
# by absolute path.
|
203
|
+
#
|
204
|
+
attr_reader :refs_by_absolute_path
|
205
|
+
|
206
|
+
#-------------------------------------------------------------------------#
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
module Pod
|
2
|
+
|
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
|
18
|
+
|
19
|
+
# @return [Sandbox] the Sandbox used by the resolver to find external
|
20
|
+
# dependencies.
|
21
|
+
#
|
22
|
+
attr_reader :sandbox
|
23
|
+
|
24
|
+
# @return [Podfile] the Podfile used by the resolver.
|
25
|
+
#
|
26
|
+
attr_reader :podfile
|
27
|
+
|
28
|
+
# @return [Array<Dependency>] the list of dependencies locked to a specific
|
29
|
+
# version.
|
30
|
+
#
|
31
|
+
attr_reader :locked_dependencies
|
32
|
+
|
33
|
+
# @param [Sandbox] sandbox @see sandbox
|
34
|
+
# @param [Podfile] podfile @see podfile
|
35
|
+
# @param [Array<Dependency>] locked_dependencies @see locked_dependencies
|
36
|
+
#
|
37
|
+
def initialize(sandbox, podfile, locked_dependencies = [])
|
38
|
+
@sandbox = sandbox
|
39
|
+
@podfile = podfile
|
40
|
+
@locked_dependencies = locked_dependencies
|
41
|
+
end
|
42
|
+
|
43
|
+
#-------------------------------------------------------------------------#
|
44
|
+
|
45
|
+
public
|
46
|
+
|
47
|
+
# @!group Resolution
|
48
|
+
|
49
|
+
# Identifies the specifications that should be installed.
|
50
|
+
#
|
51
|
+
# @return [Hash{TargetDefinition => Array<Specification>}] specs_by_target
|
52
|
+
# the specifications that need to be installed grouped by target
|
53
|
+
# definition.
|
54
|
+
#
|
55
|
+
def resolve
|
56
|
+
@cached_sources = SourcesManager.aggregate
|
57
|
+
@cached_sets = {}
|
58
|
+
@cached_specs = {}
|
59
|
+
@specs_by_target = {}
|
60
|
+
|
61
|
+
target_definitions = podfile.target_definition_list
|
62
|
+
target_definitions.each do |target|
|
63
|
+
UI.section "Resolving dependencies for target `#{target.name}' (#{target.platform})" do
|
64
|
+
@loaded_specs = []
|
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
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
cached_specs.values.sort_by(&:name)
|
72
|
+
specs_by_target
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Hash{Podfile::TargetDefinition => Array<Specification>}]
|
76
|
+
# returns the resolved specifications grouped by target.
|
77
|
+
#
|
78
|
+
# @note The returned specifications can be subspecs.
|
79
|
+
#
|
80
|
+
attr_reader :specs_by_target
|
81
|
+
|
82
|
+
#-------------------------------------------------------------------------#
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# !@ Resolution context
|
87
|
+
|
88
|
+
# @return [Source::Aggregate] A cache of the sources needed to find the
|
89
|
+
# podspecs.
|
90
|
+
#
|
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
|
95
|
+
|
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
|
106
|
+
|
107
|
+
# @return [Hash<String => Specification>] The loaded specifications grouped
|
108
|
+
# by name.
|
109
|
+
#
|
110
|
+
attr_accessor :cached_specs
|
111
|
+
|
112
|
+
#-------------------------------------------------------------------------#
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
# @!group Private helpers
|
117
|
+
|
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.
|
127
|
+
#
|
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.
|
144
|
+
#
|
145
|
+
# @return [void]
|
146
|
+
#
|
147
|
+
def find_dependency_specs(dependent_spec, dependencies, target_definition)
|
148
|
+
dependencies.each do |dependency|
|
149
|
+
locked_dep = locked_dependencies.find { |ld| ld.name == dependency.name }
|
150
|
+
dependency = locked_dep if locked_dep
|
151
|
+
|
152
|
+
UI.message("- #{dependency}", '', 2) do
|
153
|
+
set = find_cached_set(dependency)
|
154
|
+
set.required_by(dependency, dependent_spec.to_s)
|
155
|
+
|
156
|
+
unless @loaded_specs.include?(dependency.name)
|
157
|
+
spec = set.specification.subspec_by_name(dependency.name)
|
158
|
+
@loaded_specs << spec.name
|
159
|
+
cached_specs[spec.name] = spec
|
160
|
+
validate_platform(spec, target_definition)
|
161
|
+
spec.version.head = dependency.head?
|
162
|
+
|
163
|
+
spec_dependencies = spec.all_dependencies(target_definition.platform)
|
164
|
+
find_dependency_specs(spec, spec_dependencies, target_definition)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
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.
|
175
|
+
#
|
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
|
+
unless set
|
192
|
+
raise Informative, "Unable to find a specification for `#{dependency}`."
|
193
|
+
end
|
194
|
+
end
|
195
|
+
cached_sets[name]
|
196
|
+
end
|
197
|
+
|
198
|
+
# Ensures that a specification is compatible with the platform of a target.
|
199
|
+
#
|
200
|
+
# @raise If the specification is not supported by the target.
|
201
|
+
#
|
202
|
+
# @return [void]
|
203
|
+
#
|
204
|
+
def validate_platform(spec, target)
|
205
|
+
unless spec.available_platforms.any? { |p| target.platform.supports?(p) }
|
206
|
+
raise Informative, "The platform of the target `#{target.name}` " \
|
207
|
+
"(#{target.platform}) is not compatible with `#{spec}` which has " \
|
208
|
+
"a minimum requirement of #{spec.available_platforms.join(' - ')}."
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,343 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
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
|
+
# +-- User
|
16
|
+
# | +-- [Target Name]-configuration.h
|
17
|
+
# | +-- Specs
|
18
|
+
# | +-- Scripts
|
19
|
+
# |
|
20
|
+
# +-- Generated
|
21
|
+
# +-- Headers
|
22
|
+
# | +-- Private
|
23
|
+
# | | +-- [Pod Name]
|
24
|
+
# | +-- Public
|
25
|
+
# | +-- [Pod Name]
|
26
|
+
# |
|
27
|
+
# +-- Sources
|
28
|
+
# | +-- [Pod Name]
|
29
|
+
# |
|
30
|
+
# +-- Specs
|
31
|
+
# | +-- External Sources
|
32
|
+
# | +-- Normal Sources
|
33
|
+
# |
|
34
|
+
# +-- Target Support Files
|
35
|
+
# | +-- [Target Name]
|
36
|
+
# | +-- Pods-acknowledgements.markdown
|
37
|
+
# | +-- Pods-acknowledgements.plist
|
38
|
+
# | +-- Pods-dummy.m
|
39
|
+
# | +-- Pods-prefix.pch
|
40
|
+
# | +-- Pods.xcconfig
|
41
|
+
# |
|
42
|
+
# +-- Manifest.lock
|
43
|
+
# |
|
44
|
+
# +-- Pods.xcodeproj
|
45
|
+
#
|
46
|
+
# See #833
|
47
|
+
#
|
48
|
+
class Sandbox
|
49
|
+
|
50
|
+
autoload :FileAccessor, 'cocoapods/sandbox/file_accessor'
|
51
|
+
autoload :HeadersStore, 'cocoapods/sandbox/headers_store'
|
52
|
+
autoload :PathList, 'cocoapods/sandbox/path_list'
|
53
|
+
|
54
|
+
# @return [Pathname] the root of the sandbox.
|
55
|
+
#
|
56
|
+
attr_reader :root
|
57
|
+
|
58
|
+
# @return [HeadersStore] the header directory for the Pods libraries.
|
59
|
+
#
|
60
|
+
attr_reader :build_headers
|
61
|
+
|
62
|
+
# @return [HeadersStore] the header directory for the user targets.
|
63
|
+
#
|
64
|
+
attr_reader :public_headers
|
65
|
+
|
66
|
+
# @param [String, Pathname] root @see root
|
67
|
+
#
|
68
|
+
def initialize(root)
|
69
|
+
@root = Pathname.new(root)
|
70
|
+
@build_headers = HeadersStore.new(self, "BuildHeaders")
|
71
|
+
@public_headers = HeadersStore.new(self, "Headers")
|
72
|
+
@predownloaded_pods = []
|
73
|
+
@checkout_sources = {}
|
74
|
+
@local_pods = {}
|
75
|
+
FileUtils.mkdir_p(@root)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [Lockfile] the manifest which contains the information about the
|
79
|
+
# installed pods.
|
80
|
+
#
|
81
|
+
def manifest
|
82
|
+
Lockfile.from_file(manifest_path) if manifest_path.exist?
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [Project] the Pods project.
|
86
|
+
#
|
87
|
+
attr_accessor :project
|
88
|
+
|
89
|
+
# Removes the sandbox.
|
90
|
+
#
|
91
|
+
# @return [void]
|
92
|
+
#
|
93
|
+
def implode
|
94
|
+
root.rmtree
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
#
|
99
|
+
#
|
100
|
+
def clean_pod(name)
|
101
|
+
root_name = Specification.root_name(name)
|
102
|
+
unless local?(root_name)
|
103
|
+
path = pod_dir(name)
|
104
|
+
path.rmtree if path.exist?
|
105
|
+
end
|
106
|
+
podspe_path = specification_path(name)
|
107
|
+
podspe_path.rmtree if podspe_path
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [String] a string representation suitable for debugging.
|
111
|
+
#
|
112
|
+
def inspect
|
113
|
+
"#<#{self.class}> with root #{root}"
|
114
|
+
end
|
115
|
+
|
116
|
+
#-------------------------------------------------------------------------#
|
117
|
+
|
118
|
+
public
|
119
|
+
|
120
|
+
# @!group Paths
|
121
|
+
|
122
|
+
# @return [Pathname] the path of the manifest.
|
123
|
+
#
|
124
|
+
def manifest_path
|
125
|
+
root + "Manifest.lock"
|
126
|
+
end
|
127
|
+
|
128
|
+
# @return [Pathname] the path of the Pods project.
|
129
|
+
#
|
130
|
+
def project_path
|
131
|
+
root + "Pods.xcodeproj"
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns the path for the directory where to store the support files of
|
135
|
+
# a target.
|
136
|
+
#
|
137
|
+
# @param [String] name
|
138
|
+
# The name of the target.
|
139
|
+
#
|
140
|
+
# @return [Pathname] the path of the support files.
|
141
|
+
#
|
142
|
+
def library_support_files_dir(name)
|
143
|
+
# root + "Target Support Files/#{name}"
|
144
|
+
root
|
145
|
+
end
|
146
|
+
|
147
|
+
# Returns the path where the Pod with the given name is stored, taking into
|
148
|
+
# account whether the Pod is locally sourced.
|
149
|
+
#
|
150
|
+
# @param [String] name
|
151
|
+
# The name of the Pod.
|
152
|
+
#
|
153
|
+
# @return [Pathname] the path of the Pod.
|
154
|
+
#
|
155
|
+
def pod_dir(name)
|
156
|
+
root_name = Specification.root_name(name)
|
157
|
+
if local?(root_name)
|
158
|
+
Pathname.new(local_pods[root_name])
|
159
|
+
else
|
160
|
+
# root + "Sources/#{name}"
|
161
|
+
root + root_name
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# @return [Pathname] the directory where to store the documentation.
|
166
|
+
#
|
167
|
+
def documentation_dir
|
168
|
+
root + 'Documentation'
|
169
|
+
end
|
170
|
+
|
171
|
+
#-------------------------------------------------------------------------#
|
172
|
+
|
173
|
+
public
|
174
|
+
|
175
|
+
# @!group Specification store
|
176
|
+
|
177
|
+
# Returns the specification for the Pod with the given name.
|
178
|
+
#
|
179
|
+
# @param [String] name
|
180
|
+
# the name of the Pod for which the specification is requested.
|
181
|
+
#
|
182
|
+
# @return [Specification] the specification if the file is found.
|
183
|
+
#
|
184
|
+
def specification(name)
|
185
|
+
if file = specification_path(name)
|
186
|
+
Specification.from_file(file)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# @return [Pathname] the path for the directory where to store the
|
191
|
+
# specifications.
|
192
|
+
#
|
193
|
+
# @todo Migrate old installations and store the for all the pods.
|
194
|
+
# Two folders should be created `External Sources` and `Podspecs`.
|
195
|
+
#
|
196
|
+
def specifications_dir(external_source = false)
|
197
|
+
# root + "Specifications"
|
198
|
+
root + "Local Podspecs"
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns the path of the specification for the Pod with the
|
202
|
+
# given name, if one is stored.
|
203
|
+
#
|
204
|
+
# @param [String] name
|
205
|
+
# the name of the Pod for which the podspec file is requested.
|
206
|
+
#
|
207
|
+
# @return [Pathname] the path or nil.
|
208
|
+
# @return [Nil] if the podspec is not stored.
|
209
|
+
#
|
210
|
+
def specification_path(name)
|
211
|
+
path = specifications_dir + "#{name}.podspec"
|
212
|
+
path.exist? ? path : nil
|
213
|
+
end
|
214
|
+
|
215
|
+
# Stores a specification in the `Local Podspecs` folder.
|
216
|
+
#
|
217
|
+
# @param [Sandbox] sandbox
|
218
|
+
# the sandbox where the podspec should be stored.
|
219
|
+
#
|
220
|
+
# @param [String, Pathname] podspec
|
221
|
+
# The contents of the specification (String) or the path to a
|
222
|
+
# podspec file (Pathname).
|
223
|
+
#
|
224
|
+
# @todo Store all the specifications (including those not originating
|
225
|
+
# from external sources) so users can check them.
|
226
|
+
#
|
227
|
+
def store_podspec(name, podspec, external_source = false)
|
228
|
+
output_path = specifications_dir(external_source) + "#{name}.podspec"
|
229
|
+
output_path.dirname.mkpath
|
230
|
+
if podspec.is_a?(String)
|
231
|
+
output_path.open('w') { |f| f.puts(podspec) }
|
232
|
+
else
|
233
|
+
unless podspec.exist?
|
234
|
+
raise Informative, "No podspec found for `#{name}` in #{podspec}"
|
235
|
+
end
|
236
|
+
FileUtils.copy(podspec, output_path)
|
237
|
+
end
|
238
|
+
spec = Specification.from_file(output_path)
|
239
|
+
unless spec.name == name
|
240
|
+
raise Informative, "The name of the given podspec `#{spec.name}` doesn't match the expected one `#{name}`"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
#-------------------------------------------------------------------------#
|
245
|
+
|
246
|
+
public
|
247
|
+
|
248
|
+
# @!group Pods information
|
249
|
+
|
250
|
+
# Marks a Pod as pre-downloaded
|
251
|
+
#
|
252
|
+
# @param [String] name
|
253
|
+
# The name of the Pod.
|
254
|
+
#
|
255
|
+
# @return [void]
|
256
|
+
#
|
257
|
+
def store_pre_downloaded_pod(name)
|
258
|
+
root_name = Specification.root_name(name)
|
259
|
+
predownloaded_pods << root_name
|
260
|
+
end
|
261
|
+
|
262
|
+
# @return [Array<String>] The names of the pods that have been
|
263
|
+
# pre-downloaded from an external source.
|
264
|
+
#
|
265
|
+
attr_reader :predownloaded_pods
|
266
|
+
|
267
|
+
# Checks if a Pod has been pre-downloaded by the resolver in order to fetch
|
268
|
+
# the podspec.
|
269
|
+
#
|
270
|
+
# @param [String] name
|
271
|
+
# The name of the Pod.
|
272
|
+
#
|
273
|
+
# @return [Bool] Whether the Pod has been pre-downloaded.
|
274
|
+
#
|
275
|
+
def predownloaded?(name)
|
276
|
+
root_name = Specification.root_name(name)
|
277
|
+
predownloaded_pods.include?(root_name)
|
278
|
+
end
|
279
|
+
|
280
|
+
#--------------------------------------#
|
281
|
+
|
282
|
+
# Stores the local path of a Pod.
|
283
|
+
#
|
284
|
+
# @param [String] name
|
285
|
+
# The name of the Pod.
|
286
|
+
#
|
287
|
+
# @param [Hash] source
|
288
|
+
# The hash which contains the options as returned by the
|
289
|
+
# downloader.
|
290
|
+
#
|
291
|
+
# @return [void]
|
292
|
+
#
|
293
|
+
def store_checkout_source(name, source)
|
294
|
+
root_name = Specification.root_name(name)
|
295
|
+
checkout_sources[root_name] = source
|
296
|
+
end
|
297
|
+
|
298
|
+
# @return [Hash{String=>Hash}] The options necessary to recreate the exact
|
299
|
+
# checkout of a given Pod grouped by its name.
|
300
|
+
#
|
301
|
+
attr_reader :checkout_sources
|
302
|
+
|
303
|
+
#--------------------------------------#
|
304
|
+
|
305
|
+
# Stores the local path of a Pod.
|
306
|
+
#
|
307
|
+
# @param [String] name
|
308
|
+
# The name of the Pod.
|
309
|
+
#
|
310
|
+
# @param [#to_s] path
|
311
|
+
# The local path where the Pod is stored.
|
312
|
+
#
|
313
|
+
# @return [void]
|
314
|
+
#
|
315
|
+
def store_local_path(name, path)
|
316
|
+
root_name = Specification.root_name(name)
|
317
|
+
local_pods[root_name] = path.to_s
|
318
|
+
end
|
319
|
+
|
320
|
+
# @return [Hash{String=>String}] The path of the Pods with a local source
|
321
|
+
# grouped by their name.
|
322
|
+
#
|
323
|
+
# @todo Rename (e.g. `pods_with_local_path`)
|
324
|
+
#
|
325
|
+
attr_reader :local_pods
|
326
|
+
|
327
|
+
# Checks if a Pod is locally sourced?
|
328
|
+
#
|
329
|
+
# @param [String] name
|
330
|
+
# The name of the Pod.
|
331
|
+
#
|
332
|
+
# @return [Bool] Whether the Pod is locally sourced.
|
333
|
+
#
|
334
|
+
def local?(name)
|
335
|
+
root_name = Specification.root_name(name)
|
336
|
+
!local_pods[root_name].nil?
|
337
|
+
end
|
338
|
+
|
339
|
+
#-------------------------------------------------------------------------#
|
340
|
+
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|