cocoapods 0.36.4 → 0.37.0.beta.1

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.
@@ -0,0 +1,90 @@
1
+ require 'digest'
2
+
3
+ module Pod
4
+ module Downloader
5
+ # This class represents a download request for a given Pod.
6
+ #
7
+ class Request
8
+ # @return [Specification,Nil] The specification for the pod whose download
9
+ # is being requested.
10
+ #
11
+ attr_reader :spec
12
+
13
+ # @return [Boolean] Whether this download request is for a released pod.
14
+ #
15
+ attr_reader :released_pod
16
+ alias_method :released_pod?, :released_pod
17
+
18
+ # @return [String] The name of the pod whose dowload is being requested.
19
+ #
20
+ attr_reader :name
21
+
22
+ # @return [Hash<Symbol, String>] The download parameters for this request.
23
+ #
24
+ attr_reader :params
25
+
26
+ # @return [Boolean] Whether the download request is for a head download.
27
+ #
28
+ attr_reader :head
29
+ alias_method :head?, :head
30
+
31
+ # @param [Specification,Nil] spec
32
+ # see {#spec}
33
+ #
34
+ # @param [Boolean] released
35
+ # see {#released_pod}
36
+ #
37
+ # @param [String,Nil] name
38
+ # see {#name}
39
+ #
40
+ # @param [Hash<Symbol,String>,Nil] params
41
+ # see {#params}
42
+ #
43
+ # @param [Boolean] head
44
+ # see {#head}
45
+ #
46
+ def initialize(spec: nil, released: false, name: nil, params: false, head: false)
47
+ @released_pod = released
48
+ @spec = spec
49
+ @params = spec ? (spec.source && spec.source.dup) : params
50
+ @name = spec ? spec.name : name
51
+ @head = head
52
+
53
+ validate!
54
+ end
55
+
56
+ # @param [String] name
57
+ # the name of the pod being downloaded.
58
+ #
59
+ # @param [Hash<#to_s, #to_s>] params
60
+ # the download parameters of the pod being downloaded.
61
+ #
62
+ # @return [String] The slug used to store the files resulting from this
63
+ # download request.
64
+ #
65
+ def slug(name: self.name, params: self.params, spec: self.spec)
66
+ checksum = spec && spec.checksum && '-' << spec.checksum[0, 5]
67
+ if released_pod?
68
+ "Release/#{name}/#{spec.version}#{checksum}"
69
+ else
70
+ opts = params.to_a.sort_by(&:first).map { |k, v| "#{k}=#{v}" }.join('-')
71
+ digest = Digest::MD5.hexdigest(opts)
72
+ "External/#{name}/#{digest}#{checksum}"
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ # Validates that the given request is well-formed.
79
+ #
80
+ # @return [Void]
81
+ #
82
+ def validate!
83
+ raise ArgumentError, 'Requires a name' unless name
84
+ raise ArgumentError, 'Must give a spec for a released download request' if released_pod? && !spec
85
+ raise ArgumentError, 'Requires a version if released' if released_pod? && !spec.version
86
+ raise ArgumentError, 'Requires params' unless params
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,16 @@
1
+ module Pod
2
+ module Downloader
3
+ # A response to a download request.
4
+ #
5
+ # @attr [Pathname] location
6
+ # the location where this downloaded pod is stored on disk.
7
+ #
8
+ # @attr [Specification] spec
9
+ # the specification that describes this downloaded pod.
10
+ #
11
+ # @attr [Hash<Symbol, String>] checkout_options
12
+ # the downloader parameters necessary to recreate this exact download.
13
+ #
14
+ Response = Struct.new(:location, :spec, :checkout_options)
15
+ end
16
+ end
@@ -98,35 +98,31 @@ module Pod
98
98
  title = "Pre-downloading: `#{name}` #{description}"
99
99
  UI.titled_section(title, :verbose_prefix => '-> ') do
100
100
  target = sandbox.pod_dir(name)
101
- target.rmtree if target.exist?
102
- downloader = Downloader.for_target(target, params)
103
- downloader.download
104
-
105
- podspec_path = target + "#{name}.podspec"
106
- json = false
107
- unless Pathname(podspec_path).exist?
108
- podspec_path = target + "#{name}.podspec.json"
109
- json = true
110
- end
111
-
112
- store_podspec(sandbox, target + podspec_path, json)
101
+ download_result = Downloader.download(download_request, target)
102
+ spec = download_result.spec
103
+
104
+ raise Informative, "Unable to find a specification for '#{name}'." unless spec
105
+
106
+ store_podspec(sandbox, spec)
113
107
  sandbox.store_pre_downloaded_pod(name)
114
- if downloader.options_specific?
115
- source = params
116
- else
117
- source = downloader.checkout_options
118
- end
119
- sandbox.store_checkout_source(name, source)
108
+ sandbox.store_checkout_source(name, download_result.checkout_options)
120
109
  end
121
110
  end
122
111
 
112
+ def download_request
113
+ Downloader::Request.new(
114
+ :name => name,
115
+ :params => params,
116
+ )
117
+ end
118
+
123
119
  # Stores the podspec in the sandbox and marks it as from an external
124
120
  # source.
125
121
  #
126
122
  # @param [Sandbox] sandbox
127
123
  # The sandbox where the specification should be stored.
128
124
  #
129
- # @param [Pathname, String] spec
125
+ # @param [Pathname, String, Specification] spec
130
126
  # The path of the specification or its contents.
131
127
  #
132
128
  # @note All the concrete implementations of #{fetch} should invoke this
@@ -144,6 +140,9 @@ module Pod
144
140
  elsif spec.is_a?(String) && !json
145
141
  spec = Specification.from_string(spec, 'spec.podspec').to_pretty_json
146
142
  json = true
143
+ elsif spec.is_a?(Specification)
144
+ spec = spec.to_pretty_json
145
+ json = true
147
146
  end
148
147
  sandbox.store_podspec(name, spec, true, json)
149
148
  end
@@ -3,8 +3,6 @@ module Pod
3
3
  # Provides support for fetching a specification file from a path local to
4
4
  # the machine running the installation.
5
5
  #
6
- # Works with the {LocalPod::LocalSourcedPod} class.
7
- #
8
6
  class PathSource < AbstractExternalSource
9
7
  # @see AbstractExternalSource#fetch
10
8
  #
@@ -1,5 +1,5 @@
1
1
  module Pod
2
2
  # The version of the cocoapods command line tool.
3
3
  #
4
- VERSION = '0.36.4' unless defined? Pod::VERSION
4
+ VERSION = '0.37.0.beta.1' unless defined? Pod::VERSION
5
5
  end
@@ -63,8 +63,8 @@ module Pod
63
63
  fi
64
64
 
65
65
  # use filter instead of exclude so missing patterns dont' throw errors
66
- echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers/\" --filter \"- PrivateHeaders/\" ${source} ${destination}"
67
- rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" "${source}" "${destination}"
66
+ echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers/\" --filter \"- PrivateHeaders/\" --filter \"- Modules/\" ${source} ${destination}"
67
+ rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" --filter "- Modules/" "${source}" "${destination}"
68
68
  # Resign the code if required by the build settings to avoid unstable apps
69
69
  if [ "${CODE_SIGNING_REQUIRED}" == "YES" ]; then
70
70
  code_sign "${destination}/$1"
@@ -10,10 +10,15 @@ module Pod
10
10
  #
11
11
  attr_reader :target
12
12
 
13
+ # @return [Array] the private headers of the module
14
+ #
15
+ attr_accessor :private_headers
16
+
13
17
  # @param [Target] target @see target
14
18
  #
15
19
  def initialize(target)
16
20
  @target = target
21
+ @private_headers = []
17
22
  end
18
23
 
19
24
  # Generates and saves the Info.plist to the given path.
@@ -35,14 +40,24 @@ module Pod
35
40
  # @return [String]
36
41
  #
37
42
  def generate
38
- <<-eos.strip_heredoc
43
+ result = <<-eos.strip_heredoc
39
44
  framework module #{target.product_module_name} {
40
45
  umbrella header "#{target.umbrella_header_path.basename}"
41
46
 
42
47
  export *
43
48
  module * { export * }
44
- }
45
49
  eos
50
+
51
+ result << "\n#{generate_private_header_exports}" unless private_headers.empty?
52
+ result << "}\n"
53
+ end
54
+
55
+ private
56
+
57
+ def generate_private_header_exports
58
+ private_headers.reduce('') do |string, header|
59
+ string << %( private header "#{header}"\n)
60
+ end
46
61
  end
47
62
  end
48
63
  end
@@ -55,7 +55,7 @@ module Pod
55
55
 
56
56
  store_existing_checkout_options
57
57
  fetch_external_sources if allow_fetches
58
- @result.specs_by_target = resolve_dependencies
58
+ @result.specs_by_target = validate_platforms(resolve_dependencies)
59
59
  @result.specifications = generate_specifications
60
60
  @result.targets = generate_targets
61
61
  @result.sandbox_state = generate_sandbox_state
@@ -431,6 +431,26 @@ module Pod
431
431
  specs_by_target
432
432
  end
433
433
 
434
+ # Warns for any specification that is incompatible with its target.
435
+ #
436
+ # @param [Hash{TargetDefinition => Array<Spec>}] specs_by_target
437
+ # the specifications grouped by target.
438
+ #
439
+ # @return [Hash{TargetDefinition => Array<Spec>}] the specifications
440
+ # grouped by target.
441
+ #
442
+ def validate_platforms(specs_by_target)
443
+ specs_by_target.each do |target, specs|
444
+ specs.each do |spec|
445
+ unless spec.available_platforms.any? { |p| target.platform.supports?(p) }
446
+ UI.warn "The platform of the target `#{target.name}` " \
447
+ "(#{target.platform}) may not be compatible with `#{spec}` which has " \
448
+ "a minimum requirement of #{spec.available_platforms.join(' - ')}."
449
+ end
450
+ end
451
+ end
452
+ end
453
+
434
454
  # Returns the list of all the resolved the resolved specifications.
435
455
  #
436
456
  # @return [Array<Specification>] the list of the specifications.
@@ -44,12 +44,6 @@ module Pod
44
44
  def install!
45
45
  download_source unless predownloaded? || local?
46
46
  run_prepare_command
47
- rescue Informative
48
- raise
49
- rescue Object
50
- UI.notice("Error installing #{root_spec.name}")
51
- clean!
52
- raise
53
47
  end
54
48
 
55
49
  # Cleans the installations if appropriate.
@@ -80,32 +74,21 @@ module Pod
80
74
  # @return [void]
81
75
  #
82
76
  def download_source
83
- root.rmtree if root.exist?
84
- if head_pod?
85
- begin
86
- downloader.download_head
87
- @specific_source = downloader.checkout_options
88
- rescue RuntimeError => e
89
- if e.message == 'Abstract method'
90
- raise Informative, "The pod '" + root_spec.name + "' does not " \
91
- 'support the :head option, as it uses a ' + downloader.name +
92
- ' source. Remove that option to use this pod.'
93
- else
94
- raise
95
- end
96
- end
97
- else
98
- downloader.download
99
- unless downloader.options_specific?
100
- @specific_source = downloader.checkout_options
101
- end
102
- end
77
+ download_result = Downloader.download(download_request, root)
103
78
 
104
- if specific_source
79
+ if (@specific_source = download_result.checkout_options) && specific_source != root_spec.source
105
80
  sandbox.store_checkout_source(root_spec.name, specific_source)
106
81
  end
107
82
  end
108
83
 
84
+ def download_request
85
+ Downloader::Request.new(
86
+ :spec => root_spec,
87
+ :released => released?,
88
+ :head => head_pod?,
89
+ )
90
+ end
91
+
109
92
  extend Executable
110
93
  executable :bash
111
94
 
@@ -135,20 +118,8 @@ module Pod
135
118
  # @return [void]
136
119
  #
137
120
  def clean_installation
138
- clean_paths.each { |path| FileUtils.rm_rf(path) } if root.exist?
139
- end
140
-
141
- #-----------------------------------------------------------------------#
142
-
143
- public
144
-
145
- # @!group Dependencies
146
-
147
- # @return [Downloader] The downloader to use for the retrieving the
148
- # source.
149
- #
150
- def downloader
151
- @downloader ||= Downloader.for_target(root, root_spec.source.dup)
121
+ cleaner = Sandbox::PodDirCleaner.new(root, specs_by_platform)
122
+ cleaner.clean!
152
123
  end
153
124
 
154
125
  #-----------------------------------------------------------------------#
@@ -194,76 +165,8 @@ module Pod
194
165
  sandbox.head_pod?(root_spec.name)
195
166
  end
196
167
 
197
- #-----------------------------------------------------------------------#
198
-
199
- private
200
-
201
- # @!group Private helpers
202
-
203
- # @return [Array<Sandbox::FileAccessor>] the file accessors for all the
204
- # specifications on their respective platform.
205
- #
206
- def file_accessors
207
- return @file_accessors if @file_accessors
208
- @file_accessors = []
209
- specs_by_platform.each do |platform, specs|
210
- specs.each do |spec|
211
- @file_accessors << Sandbox::FileAccessor.new(path_list, spec.consumer(platform))
212
- end
213
- end
214
- @file_accessors
215
- end
216
-
217
- # @return [Sandbox::PathList] The path list for this Pod.
218
- #
219
- def path_list
220
- @path_list ||= Sandbox::PathList.new(root)
221
- end
222
-
223
- # Finds the absolute paths, including hidden ones, of the files
224
- # that are not used by the pod and thus can be safely deleted.
225
- #
226
- # @note Implementation detail: Don't use `Dir#glob` as there is an
227
- # unexplained issue (#568, #572 and #602).
228
- #
229
- # @todo The paths are down-cased for the comparison as issues similar
230
- # to #602 lead the files not being matched and so cleaning all
231
- # the files. This solution might create side effects.
232
- #
233
- # @return [Array<Strings>] The paths that can be deleted.
234
- #
235
- def clean_paths
236
- cached_used = used_files
237
- glob_options = File::FNM_DOTMATCH | File::FNM_CASEFOLD
238
- files = Pathname.glob(root + '**/*', glob_options).map(&:to_s)
239
-
240
- files.reject! do |candidate|
241
- candidate = candidate.downcase
242
- candidate.end_with?('.', '..') || cached_used.any? do |path|
243
- path = path.downcase
244
- path.include?(candidate) || candidate.include?(path)
245
- end
246
- end
247
- files
248
- end
249
-
250
- # @return [Array<String>] The absolute path of all the files used by the
251
- # specifications (according to their platform) of this Pod.
252
- #
253
- def used_files
254
- files = [
255
- file_accessors.map(&:vendored_frameworks),
256
- file_accessors.map(&:vendored_libraries),
257
- file_accessors.map(&:resource_bundle_files),
258
- file_accessors.map(&:license),
259
- file_accessors.map(&:prefix_header),
260
- file_accessors.map(&:preserve_paths),
261
- file_accessors.map(&:readme),
262
- file_accessors.map(&:resources),
263
- file_accessors.map(&:source_files),
264
- ]
265
-
266
- files.flatten.compact.map(&:to_s).uniq
168
+ def released?
169
+ !local? && !head_pod? && !predownloaded? && sandbox.specification(root_spec.name) != root_spec
267
170
  end
268
171
 
269
172
  #-----------------------------------------------------------------------#
@@ -107,12 +107,16 @@ module Pod
107
107
  # Creates the module map file which ensures that the umbrella header is
108
108
  # recognized with a customized path
109
109
  #
110
+ # @yield_param [Generator::ModuleMap]
111
+ # yielded once to configure the private headers
112
+ #
110
113
  # @return [void]
111
114
  #
112
115
  def create_module_map
113
116
  path = target.module_map_path
114
117
  UI.message "- Generating module map file at #{UI.path(path)}" do
115
118
  generator = Generator::ModuleMap.new(target)
119
+ yield generator if block_given?
116
120
  generator.save_as(path)
117
121
  add_file_to_support_group(path)
118
122