cocoapods 0.31.1 → 0.32.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,139 @@
1
+ module Pod
2
+ module ExternalSources
3
+
4
+ # Abstract class that defines the common behaviour of external sources.
5
+ #
6
+ class AbstractExternalSource
7
+
8
+ # @return [String] the name of the Pod described by this external source.
9
+ #
10
+ attr_reader :name
11
+
12
+ # @return [Hash{Symbol => String}] the hash representation of the
13
+ # external source.
14
+ #
15
+ attr_reader :params
16
+
17
+ # @return [String] the path where the podfile is defined to resolve
18
+ # relative paths.
19
+ #
20
+ attr_reader :podfile_path
21
+
22
+ # @param [String] name @see name
23
+ # @param [Hash] params @see params
24
+ # @param [String] podfile_path @see podfile_path
25
+ #
26
+ def initialize(name, params, podfile_path)
27
+ @name = name
28
+ @params = params
29
+ @podfile_path = podfile_path
30
+ end
31
+
32
+ # @return [Bool] whether an external source source is equal to another
33
+ # according to the {#name} and to the {#params}.
34
+ #
35
+ def ==(other)
36
+ return false if other.nil?
37
+ name == other.name && params == other.params
38
+ end
39
+
40
+ public
41
+
42
+ # @!group Subclasses hooks
43
+
44
+ # Fetches the external source from the remote according to the params.
45
+ #
46
+ # @param [Sandbox] sandbox
47
+ # the sandbox where the specification should be stored.
48
+ #
49
+ # @return [void]
50
+ #
51
+ def fetch(sandbox)
52
+ raise "Abstract method"
53
+ end
54
+
55
+ # @return [String] a string representation of the source suitable for UI.
56
+ #
57
+ def description
58
+ raise "Abstract method"
59
+ end
60
+
61
+ protected
62
+
63
+ # @return [String] The uri of the podspec appending the name of the file
64
+ # and expanding it if necessary.
65
+ #
66
+ # @note If the declared path is expanded only if the represents a path
67
+ # relative to the file system.
68
+ #
69
+ def normalized_podspec_path(declared_path)
70
+ if File.extname(declared_path) == '.podspec'
71
+ path_with_ext = declared_path
72
+ else
73
+ path_with_ext = "#{declared_path}/#{name}.podspec"
74
+ end
75
+ podfile_dir = File.dirname(podfile_path || '')
76
+ File.expand_path(path_with_ext, podfile_dir)
77
+ end
78
+
79
+ private
80
+
81
+ # @! Subclasses helpers
82
+
83
+ # Pre-downloads a Pod passing the options to the downloader and informing
84
+ # the sandbox.
85
+ #
86
+ # @param [Sandbox] sandbox
87
+ # The sandbox where the Pod should be downloaded.
88
+ #
89
+ # @note To prevent a double download of the repository the pod is
90
+ # marked as pre-downloaded indicating to the installer that only
91
+ # clean operations are needed.
92
+ #
93
+ # @todo The downloader configuration is the same of the
94
+ # #{PodSourceInstaller} and it needs to be kept in sync.
95
+ #
96
+ # @return [void]
97
+ #
98
+ def pre_download(sandbox)
99
+ title = "Pre-downloading: `#{name}` #{description}"
100
+ UI.titled_section(title, { :verbose_prefix => "-> " }) do
101
+ target = sandbox.root + name
102
+ target.rmtree if target.exist?
103
+ downloader = Config.instance.downloader(target, params)
104
+ downloader.download
105
+ store_podspec(sandbox, target + "#{name}.podspec")
106
+ sandbox.store_pre_downloaded_pod(name)
107
+ if downloader.options_specific?
108
+ source = params
109
+ else
110
+ source = downloader.checkout_options
111
+ end
112
+ sandbox.store_checkout_source(name, source)
113
+ end
114
+ end
115
+
116
+ # Stores the podspec in the sandbox and marks it as from an external
117
+ # source.
118
+ #
119
+ # @param [Sandbox] sandbox
120
+ # The sandbox where the specification should be stored.
121
+ #
122
+ # @param [Pathname, String] spec
123
+ # The path of the specification or its contents.
124
+ #
125
+ # @note All the concrete implementations of #{fetch} should invoke this
126
+ # method.
127
+ #
128
+ # @note The sandbox ensures that the podspec exists and that the names
129
+ # match.
130
+ #
131
+ # @return [void]
132
+ #
133
+ def store_podspec(sandbox, spec)
134
+ sandbox.store_podspec(name, spec, true)
135
+ end
136
+ end
137
+ end
138
+ end
139
+
@@ -0,0 +1,32 @@
1
+ module Pod
2
+ module ExternalSources
3
+
4
+ # Provides support for fetching a specification file from a source handled
5
+ # by the downloader. Supports all the options of the downloader
6
+ #
7
+ # @note The podspec must be in the root of the repository and should have a
8
+ # name matching the one of the dependency.
9
+ #
10
+ class DownloaderSource < AbstractExternalSource
11
+
12
+ # @see AbstractExternalSource#fetch
13
+ #
14
+ def fetch(sandbox)
15
+ pre_download(sandbox)
16
+ end
17
+
18
+ # @see AbstractExternalSource#description
19
+ #
20
+ def description
21
+ strategy = Downloader.strategy_from_options(params)
22
+ options = params.dup
23
+ url = options.delete(strategy)
24
+ result = "from `#{url}`"
25
+ options.each do |key, value|
26
+ result << ", #{key} `#{value}`"
27
+ end
28
+ result
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,58 @@
1
+ module Pod
2
+ module ExternalSources
3
+
4
+ # Provides support for fetching a specification file from a path local to
5
+ # the machine running the installation.
6
+ #
7
+ # Works with the {LocalPod::LocalSourcedPod} class.
8
+ #
9
+ class PathSource < AbstractExternalSource
10
+
11
+ # @see AbstractExternalSource#fetch
12
+ #
13
+ def fetch(sandbox)
14
+ title = "Fetching podspec for `#{name}` #{description}"
15
+ UI.titled_section(title, { :verbose_prefix => "-> " }) do
16
+ podspec = podspec_path
17
+ unless podspec.exist?
18
+ raise Informative, "No podspec found for `#{name}` in " \
19
+ "`#{declared_path}`"
20
+ end
21
+ store_podspec(sandbox, podspec)
22
+ is_absolute = absolute?(podspec)
23
+ sandbox.store_local_path(name, podspec.dirname, is_absolute)
24
+ end
25
+ end
26
+
27
+ # @see AbstractExternalSource#description
28
+ #
29
+ def description
30
+ "from `#{params[:path] || params[:local]}`"
31
+ end
32
+
33
+ private
34
+
35
+ # @!group Helpers
36
+
37
+ # @return [String] The path as declared by the user.
38
+ #
39
+ def declared_path
40
+ result = params[:path] || params[:local]
41
+ result.to_s if result
42
+ end
43
+
44
+ # @return [Pathname] The absolute path of the podspec.
45
+ #
46
+ def podspec_path
47
+ Pathname(normalized_podspec_path(declared_path))
48
+ end
49
+
50
+ # @return [Bool]
51
+ #
52
+ def absolute?(path)
53
+ Pathname(path).absolute? || path.to_s.start_with?('~')
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,45 @@
1
+ module Pod
2
+ module ExternalSources
3
+
4
+ # Provides support for fetching a specification file from an URL. Can be
5
+ # http, file, etc.
6
+ #
7
+ class PodspecSource < AbstractExternalSource
8
+
9
+ # @see AbstractExternalSource#fetch
10
+ #
11
+ def fetch(sandbox)
12
+ title = "Fetching podspec for `#{name}` #{description}"
13
+ UI.titled_section(title, { :verbose_prefix => "-> " }) do
14
+ require 'open-uri'
15
+ open(podspec_uri) { |io| store_podspec(sandbox, io.read) }
16
+ end
17
+ end
18
+
19
+ # @see AbstractExternalSource#description
20
+ #
21
+ def description
22
+ "from `#{params[:podspec]}`"
23
+ end
24
+
25
+ private
26
+
27
+ # @!group Helpers
28
+
29
+ # @return [String] The uri of the podspec appending the name of the file
30
+ # and expanding it if necessary.
31
+ #
32
+ # @note If the declared path is expanded only if the represents a path
33
+ # relative to the file system.
34
+ #
35
+ def podspec_uri
36
+ declared_path = params[:podspec].to_s
37
+ if declared_path.match(%r{^.+://})
38
+ declared_path
39
+ else
40
+ normalized_podspec_path(declared_path)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,6 +1,6 @@
1
1
  module Pod
2
2
  # The version of the cocoapods command line tool.
3
3
  #
4
- VERSION = '0.31.1' unless defined? Pod::VERSION
4
+ VERSION = '0.32.0' unless defined? Pod::VERSION
5
5
  end
6
6
 
@@ -40,9 +40,12 @@ module Pod
40
40
  # added to the top of the prefix header. For OS X `Cocoa/Cocoa.h`
41
41
  # is imported.
42
42
  #
43
+ # @note Only unique prefix_header_contents are added to the prefix header.
44
+ #
43
45
  # @return [String]
44
46
  #
45
47
  # @todo Subspecs can specify prefix header information too.
48
+ # @todo Check to see if we have a similar duplication issue with file_accessor.prefix_header.
46
49
  #
47
50
  def generate
48
51
  result = "#ifdef __OBJC__\n"
@@ -53,12 +56,18 @@ module Pod
53
56
  result << %|\n#import "#{import}"|
54
57
  end
55
58
 
56
- file_accessors.each do |file_accessor|
59
+ unique_prefix_header_contents = file_accessors.collect do |file_accessor|
60
+ file_accessor.spec_consumer.prefix_header_contents
61
+ end.compact.uniq
62
+
63
+ result << "\n"
64
+
65
+ unique_prefix_header_contents.each do |prefix_header_contents|
66
+ result << prefix_header_contents
57
67
  result << "\n"
58
- if prefix_header_contents = file_accessor.spec_consumer.prefix_header_contents
59
- result << prefix_header_contents
60
- result << "\n"
61
- end
68
+ end
69
+
70
+ file_accessors.each do |file_accessor|
62
71
  if prefix_header = file_accessor.prefix_header
63
72
  result << Pathname(prefix_header).read
64
73
  end
@@ -64,11 +64,12 @@ module Pod
64
64
  @lockfile = lockfile
65
65
  end
66
66
 
67
- # @return [Bool] Whether the installer is in update mode. In update mode
68
- # the contents of the Lockfile are not taken into account for
69
- # deciding what Pods to install.
67
+ # @return [Hash, Boolean, nil] Pods that have been requested to be
68
+ # updated or true if all Pods should be updated.
69
+ # If all Pods should been updated the contents of the Lockfile are
70
+ # not taken into account for deciding what Pods to install.
70
71
  #
71
- attr_accessor :update_mode
72
+ attr_accessor :update
72
73
 
73
74
  # Installs the Pods.
74
75
  #
@@ -169,7 +170,7 @@ module Pod
169
170
  end
170
171
 
171
172
  analyzer = Analyzer.new(sandbox, podfile, lockfile)
172
- analyzer.update_mode = update_mode
173
+ analyzer.update = update
173
174
  @analysis_result = analyzer.analyze
174
175
  @aggregate_targets = analyzer.result.targets
175
176
  end
@@ -235,7 +236,13 @@ module Pod
235
236
  title_options = { :verbose_prefix => "-> ".green }
236
237
  root_specs.sort_by(&:name).each do |spec|
237
238
  if pods_to_install.include?(spec.name)
238
- UI.titled_section("Installing #{spec}".green, title_options) do
239
+ if sandbox_state.changed.include?(spec.name) && sandbox.manifest
240
+ previous = sandbox.manifest.version(spec.name)
241
+ title = "Installing #{spec.name} #{spec.version} (was #{previous})"
242
+ else
243
+ title = "Installing #{spec}"
244
+ end
245
+ UI.titled_section(title.green, title_options) do
239
246
  install_source_of_pod(spec.name)
240
247
  end
241
248
  else
@@ -295,9 +302,10 @@ module Pod
295
302
 
296
303
  pod_names = pod_targets.map(&:pod_name).uniq
297
304
  pod_names.each do |pod_name|
298
- path = sandbox.pod_dir(pod_name)
299
305
  local = sandbox.local?(pod_name)
300
- @pods_project.add_pod_group(pod_name, path, local)
306
+ path = sandbox.pod_dir(pod_name)
307
+ was_absolute = sandbox.local_path_was_absolute?(pod_name)
308
+ @pods_project.add_pod_group(pod_name, path, local, was_absolute)
301
309
  end
302
310
 
303
311
  if config.podfile_path
@@ -33,7 +33,7 @@ module Pod
33
33
  @podfile = podfile
34
34
  @lockfile = lockfile
35
35
 
36
- @update_mode = false
36
+ @update = false
37
37
  @allow_pre_downloads = true
38
38
  @archs_by_target_def = {}
39
39
  end
@@ -91,11 +91,30 @@ module Pod
91
91
 
92
92
  # @!group Configuration
93
93
 
94
+ # @return [Hash, Boolean, nil] Pods that have been requested to be
95
+ # updated or true if all Pods should be updated
96
+ #
97
+ attr_accessor :update
98
+
94
99
  # @return [Bool] Whether the version of the dependencies which did non
95
100
  # change in the Podfile should be locked.
96
101
  #
97
- attr_accessor :update_mode
98
- alias_method :update_mode?, :update_mode
102
+ def update_mode?
103
+ !!update
104
+ end
105
+
106
+ # @return [Symbol] Whether and how the dependencies in the Podfile
107
+ # should be updated.
108
+ #
109
+ def update_mode
110
+ if !update
111
+ :none
112
+ elsif update == true
113
+ :all
114
+ elsif update[:pods] != nil
115
+ :selected
116
+ end
117
+ end
99
118
 
100
119
  # @return [Bool] Whether the analysis allows pre-downloads and thus
101
120
  # modifications to the sandbox.
@@ -219,10 +238,15 @@ module Pod
219
238
  # that prevent the resolver to update a Pod.
220
239
  #
221
240
  def generate_version_locking_dependencies
222
- if update_mode?
241
+ if update_mode == :all
223
242
  []
224
243
  else
225
- result.podfile_state.unchanged.map do |pod|
244
+ locking_pods = result.podfile_state.unchanged
245
+ if update_mode == :selected
246
+ # If selected Pods should been updated, filter them out of the list
247
+ locking_pods = locking_pods.select { |pod| !update[:pods].include?(pod) }
248
+ end
249
+ locking_pods.map do |pod|
226
250
  lockfile.dependency_to_lock_pod_named(pod)
227
251
  end
228
252
  end
@@ -252,10 +276,14 @@ module Pod
252
276
  deps_to_fetch = []
253
277
  deps_to_fetch_if_needed = []
254
278
  deps_with_external_source = podfile.dependencies.select { |dep| dep.external_source }
255
- if update_mode?
279
+
280
+ if update_mode == :all
256
281
  deps_to_fetch = deps_with_external_source
257
282
  else
258
283
  pods_to_fetch = result.podfile_state.added + result.podfile_state.changed
284
+ if update_mode == :selected
285
+ pods_to_fetch += update[:pods]
286
+ end
259
287
  deps_to_fetch = deps_with_external_source.select { |dep| pods_to_fetch.include?(dep.root_name) }
260
288
  deps_to_fetch_if_needed = deps_with_external_source.select { |dep| result.podfile_state.unchanged.include?(dep.root_name) }
261
289
  deps_to_fetch += deps_to_fetch_if_needed.select { |dep| sandbox.specification(dep.root_name).nil? || !dep.external_source[:local].nil? || !dep.external_source[:path].nil? }
@@ -316,7 +344,7 @@ module Pod
316
344
  def generate_sandbox_state
317
345
  sandbox_state = nil
318
346
  UI.section "Comparing resolved specification to the sandbox manifest" do
319
- sandbox_analyzer = SandboxAnalyzer.new(sandbox, result.specifications, update_mode, lockfile)
347
+ sandbox_analyzer = SandboxAnalyzer.new(sandbox, result.specifications, update_mode?, lockfile)
320
348
  sandbox_state = sandbox_analyzer.analyze
321
349
  sandbox_state.print
322
350
  end