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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1296 -0
  3. data/LICENSE +20 -0
  4. data/README.md +94 -0
  5. data/bin/pod +16 -0
  6. data/bin/sandbox-pod +120 -0
  7. data/lib/cocoapods.rb +77 -0
  8. data/lib/cocoapods/command.rb +116 -0
  9. data/lib/cocoapods/command/help.rb +23 -0
  10. data/lib/cocoapods/command/inter_process_communication.rb +178 -0
  11. data/lib/cocoapods/command/list.rb +77 -0
  12. data/lib/cocoapods/command/outdated.rb +56 -0
  13. data/lib/cocoapods/command/podfile_info.rb +91 -0
  14. data/lib/cocoapods/command/project.rb +88 -0
  15. data/lib/cocoapods/command/push.rb +172 -0
  16. data/lib/cocoapods/command/repo.rb +145 -0
  17. data/lib/cocoapods/command/search.rb +61 -0
  18. data/lib/cocoapods/command/setup.rb +134 -0
  19. data/lib/cocoapods/command/spec.rb +590 -0
  20. data/lib/cocoapods/config.rb +231 -0
  21. data/lib/cocoapods/downloader.rb +59 -0
  22. data/lib/cocoapods/executable.rb +118 -0
  23. data/lib/cocoapods/external_sources.rb +363 -0
  24. data/lib/cocoapods/file_list.rb +36 -0
  25. data/lib/cocoapods/gem_version.rb +7 -0
  26. data/lib/cocoapods/generator/acknowledgements.rb +107 -0
  27. data/lib/cocoapods/generator/acknowledgements/markdown.rb +40 -0
  28. data/lib/cocoapods/generator/acknowledgements/plist.rb +64 -0
  29. data/lib/cocoapods/generator/bridge_support.rb +22 -0
  30. data/lib/cocoapods/generator/copy_resources_script.rb +54 -0
  31. data/lib/cocoapods/generator/dummy_source.rb +22 -0
  32. data/lib/cocoapods/generator/prefix_header.rb +82 -0
  33. data/lib/cocoapods/generator/target_environment_header.rb +86 -0
  34. data/lib/cocoapods/generator/xcconfig.rb +185 -0
  35. data/lib/cocoapods/hooks/installer_representation.rb +134 -0
  36. data/lib/cocoapods/hooks/library_representation.rb +94 -0
  37. data/lib/cocoapods/hooks/pod_representation.rb +74 -0
  38. data/lib/cocoapods/installer.rb +571 -0
  39. data/lib/cocoapods/installer/analyzer.rb +559 -0
  40. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
  41. data/lib/cocoapods/installer/file_references_installer.rb +179 -0
  42. data/lib/cocoapods/installer/pod_source_installer.rb +248 -0
  43. data/lib/cocoapods/installer/target_installer.rb +379 -0
  44. data/lib/cocoapods/installer/user_project_integrator.rb +180 -0
  45. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +224 -0
  46. data/lib/cocoapods/library.rb +202 -0
  47. data/lib/cocoapods/open_uri.rb +24 -0
  48. data/lib/cocoapods/project.rb +209 -0
  49. data/lib/cocoapods/resolver.rb +212 -0
  50. data/lib/cocoapods/sandbox.rb +343 -0
  51. data/lib/cocoapods/sandbox/file_accessor.rb +217 -0
  52. data/lib/cocoapods/sandbox/headers_store.rb +96 -0
  53. data/lib/cocoapods/sandbox/path_list.rb +208 -0
  54. data/lib/cocoapods/sources_manager.rb +276 -0
  55. data/lib/cocoapods/user_interface.rb +304 -0
  56. data/lib/cocoapods/user_interface/error_report.rb +101 -0
  57. data/lib/cocoapods/validator.rb +350 -0
  58. metadata +238 -0
@@ -0,0 +1,231 @@
1
+ module Pod
2
+
3
+ # Stores the global configuration of CocoaPods.
4
+ #
5
+ class Config
6
+
7
+ # The default settings for the configuration.
8
+ #
9
+ # Users can specify custom settings in `~/.cocoapods/config.yaml`.
10
+ # An example of the contents of this file might look like:
11
+ #
12
+ # ---
13
+ # skip_repo_update: true
14
+ # new_version_message: false
15
+ #
16
+ DEFAULTS = {
17
+ :verbose => false,
18
+ :silent => false,
19
+ :skip_repo_update => false,
20
+ :aggressive_cache => false,
21
+
22
+ :clean => true,
23
+ :integrate_targets => true,
24
+ :new_version_message => true,
25
+ }
26
+
27
+ #--------------------------------------#
28
+
29
+ # @!group UI
30
+
31
+ # @return [Bool] Whether CocoaPods should provide detailed output about the
32
+ # performed actions.
33
+ #
34
+ attr_accessor :verbose
35
+ alias_method :verbose?, :verbose
36
+
37
+ # @return [Bool] Whether CocoaPods should produce not output.
38
+ #
39
+ attr_accessor :silent
40
+ alias_method :silent?, :silent
41
+
42
+ # @return [Bool] Whether a message should be printed when a new version of
43
+ # CocoaPods is available.
44
+ #
45
+ attr_accessor :new_version_message
46
+ alias_method :new_version_message?, :new_version_message
47
+
48
+ #--------------------------------------#
49
+
50
+ # @!group Installation
51
+
52
+ # @return [Bool] Whether the installer should clean after the installation.
53
+ #
54
+ attr_accessor :clean
55
+ alias_method :clean?, :clean
56
+
57
+ # @return [Bool] Whether CocoaPods should integrate a user target and build
58
+ # the workspace or just create the Pods project.
59
+ #
60
+ attr_accessor :integrate_targets
61
+ alias_method :integrate_targets?, :integrate_targets
62
+
63
+
64
+ # @return [Bool] Whether the installer should skip the repos update.
65
+ #
66
+ attr_accessor :skip_repo_update
67
+ alias_method :skip_repo_update?, :skip_repo_update
68
+
69
+ # Allows to set whether the downloader should use more aggressive caching
70
+ # options.
71
+ #
72
+ # @note The aggressive cache has lead to issues if a tag is updated to
73
+ # point to another commit.
74
+ #
75
+ attr_writer :aggressive_cache
76
+
77
+ # @return [Bool] Whether the downloader should use more aggressive caching
78
+ # options.
79
+ #
80
+ def aggressive_cache?
81
+ @aggressive_cache || (ENV['CP_AGGRESSIVE_CACHE'] != 'FALSE')
82
+ end
83
+
84
+ #--------------------------------------#
85
+
86
+ # @!group Initialization
87
+
88
+ def initialize
89
+ configure_with(DEFAULTS)
90
+
91
+ if user_settings_file.exist?
92
+ require 'yaml'
93
+ user_settings = YAML.load_file(user_settings_file)
94
+ configure_with(user_settings)
95
+ end
96
+ end
97
+
98
+ def verbose
99
+ @verbose && !silent
100
+ end
101
+
102
+ #--------------------------------------#
103
+
104
+ # @!group Paths
105
+
106
+ # @return [Pathname] the directory where the CocoaPods sources are stored.
107
+ #
108
+ def repos_dir
109
+ @repos_dir ||= Pathname.new(ENV['CP_REPOS_DIR'] || "~/.cocoapods").expand_path
110
+ end
111
+
112
+ attr_writer :repos_dir
113
+
114
+ # @return [Pathname] the root of the CocoaPods installation where the
115
+ # Podfile is located.
116
+ #
117
+ def installation_root
118
+ @installation_root ||= Pathname.pwd
119
+ end
120
+
121
+ attr_writer :installation_root
122
+ alias :project_root :installation_root
123
+
124
+ # @return [Pathname] The root of the sandbox.
125
+ #
126
+ def sandbox_root
127
+ @sandbox_root ||= installation_root + 'Pods'
128
+ end
129
+
130
+ attr_writer :sandbox_root
131
+ alias :project_pods_root :sandbox_root
132
+
133
+ # @return [Sandbox] The sandbox of the current project.
134
+ #
135
+ def sandbox
136
+ @sandbox ||= Sandbox.new(sandbox_root)
137
+ end
138
+
139
+ # @return [Podfile] The Podfile to use for the current execution.
140
+ #
141
+ def podfile
142
+ @podfile ||= Podfile.from_file(podfile_path) if podfile_path.exist?
143
+ end
144
+ attr_writer :podfile
145
+
146
+ # @return [Lockfile] The Lockfile to use for the current execution.
147
+ #
148
+ def lockfile
149
+ @lockfile ||= Lockfile.from_file(lockfile_path) if lockfile_path.exist?
150
+ end
151
+
152
+ #--------------------------------------#
153
+
154
+ # @!group Helpers
155
+
156
+ # private
157
+
158
+ # @return [Pathname] The path of the file which contains the user settings.
159
+ #
160
+ def user_settings_file
161
+ repos_dir + "config.yaml"
162
+ end
163
+
164
+ # Sets the values of the attributes with the given hash.
165
+ #
166
+ # @param [Hash{String,Symbol => Object}] values_by_key
167
+ # The values of the attributes grouped by key.
168
+ #
169
+ # @return [void]
170
+ #
171
+ def configure_with(values_by_key)
172
+ return unless values_by_key
173
+ values_by_key.each do |key, value|
174
+ self.instance_variable_set("@#{key}", value)
175
+ end
176
+ end
177
+
178
+ # Returns the path of the Podfile.
179
+ #
180
+ # @note The Podfile can be named either `CocoaPods.podfile` or `Podfile`.
181
+ # The first is preferred as it allows to specify an OS X UTI.
182
+ #
183
+ def podfile_path
184
+ unless @podfile_path
185
+ path = installation_root + 'CocoaPods.podfile.yaml'
186
+ path = installation_root + 'CocoaPods.podfile' unless path.exist?
187
+ path = installation_root + 'Podfile' unless path.exist?
188
+ @podfile_path = path
189
+ end
190
+ @podfile_path
191
+ end
192
+
193
+ # Returns the path of the Lockfile.
194
+ #
195
+ # @note The Lockfile is named `Podfile.lock`.
196
+ #
197
+ def lockfile_path
198
+ @lockfile_path ||= installation_root + 'Podfile.lock'
199
+ end
200
+
201
+ #--------------------------------------#
202
+
203
+ # @return [Config] the current config instance creating one if needed.
204
+ #
205
+ def self.instance
206
+ @instance ||= new
207
+ end
208
+
209
+ # Sets the current config instance. If set to nil the config will be
210
+ # recreated when needed.
211
+ #
212
+ # @param [Config, Nil] the instance.
213
+ #
214
+ # @return [void]
215
+ #
216
+ def self.instance=(instance)
217
+ @instance = instance
218
+ end
219
+
220
+ #-------------------------------------------------------------------------#
221
+
222
+ # Provides support for accessing the configuration instance in other
223
+ # scopes.
224
+ #
225
+ module Mixin
226
+ def config
227
+ Config.instance
228
+ end
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,59 @@
1
+ require 'cocoapods-downloader'
2
+
3
+ module Pod
4
+ module Downloader
5
+ class Base
6
+
7
+ override_api do
8
+
9
+ def execute_command(executable, command, raise_on_failure = false)
10
+ Executable.execute_command(executable, command, raise_on_failure)
11
+ end
12
+
13
+ # Indicates that an action will be performed. The action is passed as a
14
+ # block.
15
+ #
16
+ # @param [String] message
17
+ # The message associated with the action.
18
+ #
19
+ # @yield The action, this block is always executed.
20
+ #
21
+ # @return [void]
22
+ #
23
+ def ui_action(message)
24
+ UI.section(" > #{message}", '', 1) do
25
+ yield
26
+ end
27
+ end
28
+
29
+ # Indicates that a minor action will be performed. The action is passed
30
+ # as a block.
31
+ #
32
+ # @param [String] message
33
+ # The message associated with the action.
34
+ #
35
+ # @yield The action, this block is always executed.
36
+ #
37
+ # @return [void]
38
+ #
39
+ def ui_sub_action(message)
40
+ UI.section(" > #{message}", '', 2) do
41
+ yield
42
+ end
43
+ end
44
+
45
+ # Prints an UI message.
46
+ #
47
+ # @param [String] message
48
+ # The message associated with the action.
49
+ #
50
+ # @return [void]
51
+ #
52
+ def ui_message(message)
53
+ UI.puts message
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,118 @@
1
+ module Pod
2
+
3
+ # Module which provides support for running executables.
4
+ #
5
+ # In a class it can be used as:
6
+ #
7
+ # extend Executable
8
+ # executable :git
9
+ #
10
+ # This will create two methods `git` and `git!` both accept a command but
11
+ # the later will raise on non successful executions. The methods return the
12
+ # output of the command.
13
+ #
14
+ module Executable
15
+
16
+ # Creates the methods for the executable with the given name.
17
+ #
18
+ # @param [Symbol] name
19
+ # the name of the executable.
20
+ #
21
+ # @return [void]
22
+ #
23
+ def executable(name)
24
+
25
+ define_method(name) do |command|
26
+ Executable.execute_command(name, command, false)
27
+ end
28
+
29
+ define_method(name.to_s + "!") do |command|
30
+ Executable.execute_command(name, command, true)
31
+ end
32
+ end
33
+
34
+ # Executes the given command displaying it if in verbose mode.
35
+ #
36
+ # @param [String] bin
37
+ # The binary to use.
38
+ #
39
+ # @param [String] command
40
+ # The command to send to the binary.
41
+ #
42
+ # @param [Bool] raise_on_failure
43
+ # Whether it should raise if the command fails.
44
+ #
45
+ # @raise If the executable could not be located.
46
+ #
47
+ # @raise If the command fails and the `raise_on_failure` is set to true.
48
+ #
49
+ # @return [String] the output of the command (STDOUT and STDERR).
50
+ #
51
+ # @todo Find a way to display the live output of the commands.
52
+ #
53
+ def self.execute_command(executable, command, raise_on_failure)
54
+
55
+ bin = `which #{executable}`.strip
56
+ raise Informative, "Unable to locate the executable `#{executable}`" if bin.empty?
57
+
58
+ require 'open4'
59
+
60
+ full_command = "#{bin} #{command}"
61
+
62
+ if Config.instance.verbose?
63
+ UI.message("$ #{full_command}")
64
+ stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
65
+ else
66
+ stdout, stderr = Indenter.new, Indenter.new
67
+ end
68
+
69
+ options = {:stdout => stdout, :stderr => stderr, :status => true}
70
+ status = Open4.spawn(full_command, options)
71
+ output = stdout.join("\n") + stderr.join("\n")
72
+ unless status.success?
73
+ if raise_on_failure
74
+ raise Informative, "#{name} #{command}\n\n#{output}"
75
+ else
76
+ UI.message("[!] Failed: #{full_command}".red)
77
+ end
78
+ end
79
+ output
80
+ end
81
+
82
+ #-------------------------------------------------------------------------#
83
+
84
+ # Helper class that allows to write to an {IO} instance taking into account
85
+ # the UI indentation lever.
86
+ #
87
+ class Indenter < ::Array
88
+
89
+ # @return [Fixnum] The indentation level of the UI.
90
+ #
91
+ attr_accessor :indent
92
+
93
+ # @return [IO] the {IO} to which the output should be printed.
94
+ #
95
+ attr_accessor :io
96
+
97
+ # @param [IO] io @see io
98
+ #
99
+ def initialize(io = nil)
100
+ @io = io
101
+ @indent = ' ' * UI.indentation_level
102
+ end
103
+
104
+ # Stores a portion of the output and prints it to the {IO} instance.
105
+ #
106
+ # @param [String] value
107
+ # the output to print.
108
+ #
109
+ # @return [void]
110
+ #
111
+ def <<(value)
112
+ super
113
+ ensure
114
+ @io << "#{ indent }#{ value }" if @io
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,363 @@
1
+ module Pod
2
+
3
+ # Provides support for initializing the correct concrete class of an external
4
+ # source.
5
+ #
6
+ module ExternalSources
7
+
8
+ # @return [AbstractExternalSource] an initialized instance of the concrete
9
+ # external source class associated with the option specified in the
10
+ # hash.
11
+ #
12
+ def self.from_dependency(dependency, podfile_path)
13
+ name = dependency.root_name
14
+ params = dependency.external_source
15
+
16
+ klass = if params.key?(:git) then GitSource
17
+ elsif params.key?(:svn) then SvnSource
18
+ elsif params.key?(:hg) then MercurialSource
19
+ elsif params.key?(:podspec) then PodspecSource
20
+ elsif params.key?(:path) then PathSource
21
+ end
22
+
23
+ if params.key?(:local)
24
+ klass = PathSource
25
+ UI.warn "The `:local` option of the Podfile has been renamed to `:path` and is deprecated." \
26
+ end
27
+
28
+ if klass
29
+ klass.new(name, params, podfile_path)
30
+ else
31
+ msg = "Unknown external source parameters for `#{name}`: `#{params}`"
32
+ raise Informative, msg
33
+ end
34
+ end
35
+
36
+ #-------------------------------------------------------------------------#
37
+
38
+ # Abstract class that defines the common behaviour of external sources.
39
+ #
40
+ class AbstractExternalSource
41
+
42
+ # @return [String] the name of the Pod described by this external source.
43
+ #
44
+ attr_reader :name
45
+
46
+ # @return [Hash{Symbol => String}] the hash representation of the
47
+ # external source.
48
+ #
49
+ attr_reader :params
50
+
51
+ # @return [String] the path where the podfile is defined to resolve
52
+ # relative paths.
53
+ #
54
+ attr_reader :podfile_path
55
+
56
+ # @param [String] name @see name
57
+ # @param [Hash] params @see params
58
+ # @param [String] podfile_path @see podfile_path
59
+ #
60
+ def initialize(name, params, podfile_path)
61
+ @name = name
62
+ @params = params
63
+ @podfile_path = podfile_path
64
+ end
65
+
66
+ # @return [Bool] whether an external source source is equal to another
67
+ # according to the {#name} and to the {#params}.
68
+ #
69
+ def ==(other)
70
+ return false if other.nil?
71
+ name == other.name && params == other.params
72
+ end
73
+
74
+ #--------------------------------------#
75
+
76
+ public
77
+
78
+ # @!group Fetching
79
+
80
+ # Fetches the external source from the remote according to the params.
81
+ #
82
+ # @param [Sandbox] sandbox
83
+ # the sandbox where the specification should be stored.
84
+ #
85
+ # @return [void]
86
+ #
87
+ def fetch(sandbox)
88
+ raise "Abstract method"
89
+ end
90
+
91
+ #--------------------------------------#
92
+
93
+ public
94
+
95
+ # @!group Subclasses hooks
96
+
97
+ # Fetches the external source from the remote according to the params.
98
+ #
99
+ # @param [Sandbox] sandbox
100
+ # the sandbox where the specification should be stored.
101
+ #
102
+ # @return [void]
103
+ #
104
+ def fetch(sandbox)
105
+ raise "Abstract method"
106
+ end
107
+
108
+ # @return [String] a string representation of the source suitable for UI.
109
+ #
110
+ def description
111
+ raise "Abstract method"
112
+ end
113
+
114
+ #--------------------------------------#
115
+
116
+ private
117
+
118
+ # @! Subclasses helpers
119
+
120
+ # Pre-downloads a Pod passing the options to the downloader and informing
121
+ # the sandbox.
122
+ #
123
+ # @param [Sandbox] sandbox
124
+ # The sandbox where the Pod should be downloaded.
125
+ #
126
+ # @note To prevent a double download of the repository the pod is
127
+ # marked as pre-downloaded indicating to the installer that only
128
+ # clean operations are needed.
129
+ #
130
+ # @todo The downloader configuration is the same of the
131
+ # #{PodSourceInstaller} and it needs to be kept in sync.
132
+ #
133
+ # @return [void]
134
+ #
135
+ def pre_download(sandbox)
136
+ UI.titled_section("Pre-downloading: `#{name}` #{description}", { :verbose_prefix => "-> " }) do
137
+ target = sandbox.root + name
138
+ target.rmtree if target.exist?
139
+ downloader = Downloader.for_target(target, params)
140
+ downloader.cache_root = CACHE_ROOT.to_s
141
+ downloader.max_cache_size = MAX_CACHE_SIZE
142
+ downloader.aggressive_cache = false
143
+ downloader.download
144
+ store_podspec(sandbox, target + "#{name}.podspec")
145
+ sandbox.store_pre_downloaded_pod(name)
146
+ if downloader.options_specific?
147
+ source = params
148
+ else
149
+ source = downloader.checkout_options
150
+ end
151
+ sandbox.store_checkout_source(name, source)
152
+ end
153
+ end
154
+
155
+ # Stores the podspec in the sandbox and marks it as from an external
156
+ # source.
157
+ #
158
+ # @param [Sandbox] sandbox
159
+ # The sandbox where the specification should be stored.
160
+ #
161
+ # @param [Pathname, String] spec
162
+ # The path of the specification or its contents.
163
+ #
164
+ # @note All the concrete implementations of #{fetch} should invoke this
165
+ # method.
166
+ #
167
+ # @note The sandbox ensures that the podspec exists and that the names
168
+ # match.
169
+ #
170
+ # @return [void]
171
+ #
172
+ def store_podspec(sandbox, spec)
173
+ sandbox.store_podspec(name, spec, true)
174
+ end
175
+
176
+ end
177
+
178
+ #-------------------------------------------------------------------------#
179
+
180
+ # Provides support for fetching a specification file from a Git remote.
181
+ #
182
+ # Supports all the options of the downloader (is similar to the git key of
183
+ # `source` attribute of a specification).
184
+ #
185
+ # @note The podspec must be in the root of the repository and should have a
186
+ # name matching the one of the dependency.
187
+ #
188
+ class GitSource < AbstractExternalSource
189
+
190
+ # @see AbstractExternalSource#fetch
191
+ #
192
+ def fetch(sandbox)
193
+ pre_download(sandbox)
194
+ end
195
+
196
+ # @see AbstractExternalSource#description
197
+ #
198
+ def description
199
+ "from `#{params[:git]}`".tap do |description|
200
+ description << ", commit `#{params[:commit]}`" if params[:commit]
201
+ description << ", branch `#{params[:branch]}`" if params[:branch]
202
+ description << ", tag `#{params[:tag]}`" if params[:tag]
203
+ end
204
+ end
205
+ end
206
+
207
+ #-------------------------------------------------------------------------#
208
+
209
+ # Provides support for fetching a specification file from a SVN source
210
+ # remote.
211
+ #
212
+ # Supports all the options of the downloader (is similar to the git key of
213
+ # `source` attribute of a specification).
214
+ #
215
+ # @note The podspec must be in the root of the repository and should have a
216
+ # name matching the one of the dependency.
217
+ #
218
+ class SvnSource < AbstractExternalSource
219
+
220
+ # @see AbstractExternalSource#fetch
221
+ #
222
+ def fetch(sandbox)
223
+ pre_download(sandbox)
224
+ end
225
+
226
+ # @see AbstractExternalSource#description
227
+ #
228
+ def description
229
+ "from `#{params[:svn]}`".tap do |description|
230
+ description << ", folder `#{params[:folder]}`" if params[:folder]
231
+ description << ", tag `#{params[:tag]}`" if params[:tag]
232
+ description << ", revision `#{params[:revision]}`" if params[:revision]
233
+ end
234
+ end
235
+ end
236
+
237
+ #-------------------------------------------------------------------------#
238
+
239
+ # Provides support for fetching a specification file from a Mercurial
240
+ # source remote.
241
+ #
242
+ # Supports all the options of the downloader (is similar to the git key of
243
+ # `source` attribute of a specification).
244
+ #
245
+ # @note The podspec must be in the root of the repository and should have a
246
+ # name matching the one of the dependency.
247
+ #
248
+ class MercurialSource < AbstractExternalSource
249
+
250
+ # @see AbstractExternalSource#fetch
251
+ #
252
+ def fetch(sandbox)
253
+ pre_download(sandbox)
254
+ end
255
+
256
+ # @see AbstractExternalSource#description
257
+ #
258
+ def description
259
+ "from `#{params[:hg]}`".tap do |description|
260
+ description << ", revision `#{params[:revision]}`" if params[:revision]
261
+ end
262
+ end
263
+ end
264
+
265
+ #-------------------------------------------------------------------------#
266
+
267
+ # Provides support for fetching a specification file from an URL. Can be
268
+ # http, file, etc.
269
+ #
270
+ class PodspecSource < AbstractExternalSource
271
+
272
+ # @see AbstractExternalSource#fetch
273
+ #
274
+ def fetch(sandbox)
275
+ UI.titled_section("Fetching podspec for `#{name}` #{description}", { :verbose_prefix => "-> " }) do
276
+
277
+ require 'open-uri'
278
+ open(podspec_uri) { |io| store_podspec(sandbox, io.read) }
279
+ end
280
+ end
281
+
282
+ # @see AbstractExternalSource#description
283
+ #
284
+ def description
285
+ "from `#{params[:podspec]}`"
286
+ end
287
+
288
+ #--------------------------------------#
289
+
290
+ private
291
+
292
+ # @!group Helpers
293
+
294
+ # @return [String] The uri of the podspec appending the name of the file
295
+ # and expanding it if necessary.
296
+ #
297
+ # @note If the declared path is expanded only if the represents a path
298
+ # relative to the file system.
299
+ #
300
+ def podspec_uri
301
+ declared_path = params[:podspec].to_s
302
+ if declared_path.match(%r{^.+://})
303
+ declared_path
304
+ else
305
+ path_with_ext = File.extname(declared_path) == '.podspec' ? declared_path : "#{declared_path}/#{name}.podspec"
306
+ podfile_dir = File.dirname(podfile_path || '')
307
+ absolute_path = File.expand_path(path_with_ext, podfile_dir)
308
+ absolute_path
309
+ end
310
+ end
311
+ end
312
+
313
+ #-------------------------------------------------------------------------#
314
+
315
+ # Provides support for fetching a specification file from a path local to
316
+ # the machine running the installation.
317
+ #
318
+ # Works with the {LocalPod::LocalSourcedPod} class.
319
+ #
320
+ class PathSource < AbstractExternalSource
321
+
322
+ # @see AbstractExternalSource#fetch
323
+ #
324
+ def fetch(sandbox)
325
+ UI.titled_section("Fetching podspec for `#{name}` #{description}", { :verbose_prefix => "-> " }) do
326
+ podspec = podspec_path
327
+ store_podspec(sandbox, podspec)
328
+ sandbox.store_local_path(name, podspec.dirname)
329
+ end
330
+ end
331
+
332
+ # @see AbstractExternalSource#description
333
+ #
334
+ def description
335
+ "from `#{params[:path] || params[:local]}`"
336
+ end
337
+
338
+ #--------------------------------------#
339
+
340
+ private
341
+
342
+ # @!group Helpers
343
+
344
+ # @return [Pathname] the path of the podspec.
345
+ #
346
+ def podspec_path
347
+ declared_path = (params[:path] || params[:local]).to_s
348
+ path_with_ext = File.extname(declared_path) == '.podspec' ? declared_path : "#{declared_path}/#{name}.podspec"
349
+ podfile_dir = File.dirname(podfile_path || '')
350
+ absolute_path = File.expand_path(path_with_ext, podfile_dir)
351
+ pathname = Pathname.new(absolute_path)
352
+
353
+ unless pathname.exist?
354
+ raise Informative, "No podspec found for `#{name}` in `#{params[:local]}`"
355
+ end
356
+ pathname
357
+ end
358
+ end
359
+
360
+ #-------------------------------------------------------------------------#
361
+
362
+ end
363
+ end