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.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +108 -0
  3. data/README.md +3 -3
  4. data/bin/pod +1 -1
  5. data/lib/cocoapods.rb +31 -31
  6. data/lib/cocoapods/command.rb +62 -107
  7. data/lib/cocoapods/command/inter_process_communication.rb +103 -0
  8. data/lib/cocoapods/command/list.rb +45 -44
  9. data/lib/cocoapods/command/outdated.rb +28 -25
  10. data/lib/cocoapods/command/project.rb +90 -0
  11. data/lib/cocoapods/command/push.rb +50 -32
  12. data/lib/cocoapods/command/repo.rb +125 -155
  13. data/lib/cocoapods/command/search.rb +23 -12
  14. data/lib/cocoapods/command/setup.rb +103 -64
  15. data/lib/cocoapods/command/spec.rb +329 -90
  16. data/lib/cocoapods/config.rb +197 -44
  17. data/lib/cocoapods/downloader.rb +47 -34
  18. data/lib/cocoapods/executable.rb +98 -41
  19. data/lib/cocoapods/external_sources.rb +325 -0
  20. data/lib/cocoapods/file_list.rb +8 -1
  21. data/lib/cocoapods/gem_version.rb +7 -0
  22. data/lib/cocoapods/generator/acknowledgements.rb +71 -7
  23. data/lib/cocoapods/generator/acknowledgements/markdown.rb +10 -9
  24. data/lib/cocoapods/generator/acknowledgements/plist.rb +9 -8
  25. data/lib/cocoapods/generator/copy_resources_script.rb +2 -2
  26. data/lib/cocoapods/generator/documentation.rb +153 -37
  27. data/lib/cocoapods/generator/prefix_header.rb +82 -0
  28. data/lib/cocoapods/generator/target_header.rb +58 -0
  29. data/lib/cocoapods/generator/xcconfig.rb +130 -0
  30. data/lib/cocoapods/hooks/installer_representation.rb +123 -0
  31. data/lib/cocoapods/hooks/library_representation.rb +79 -0
  32. data/lib/cocoapods/hooks/pod_representation.rb +74 -0
  33. data/lib/cocoapods/installer.rb +398 -147
  34. data/lib/cocoapods/installer/analyzer.rb +556 -0
  35. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
  36. data/lib/cocoapods/installer/file_references_installer.rb +179 -0
  37. data/lib/cocoapods/installer/pod_source_installer.rb +289 -0
  38. data/lib/cocoapods/installer/target_installer.rb +307 -112
  39. data/lib/cocoapods/installer/user_project_integrator.rb +140 -176
  40. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +193 -0
  41. data/lib/cocoapods/library.rb +195 -0
  42. data/lib/cocoapods/open_uri.rb +16 -14
  43. data/lib/cocoapods/project.rb +175 -52
  44. data/lib/cocoapods/resolver.rb +151 -164
  45. data/lib/cocoapods/sandbox.rb +276 -54
  46. data/lib/cocoapods/sandbox/file_accessor.rb +210 -0
  47. data/lib/cocoapods/sandbox/headers_store.rb +96 -0
  48. data/lib/cocoapods/sandbox/path_list.rb +178 -0
  49. data/lib/cocoapods/sources_manager.rb +218 -0
  50. data/lib/cocoapods/user_interface.rb +82 -18
  51. data/lib/cocoapods/{command → user_interface}/error_report.rb +5 -5
  52. data/lib/cocoapods/validator.rb +379 -0
  53. metadata +74 -55
  54. data/lib/cocoapods/command/install.rb +0 -55
  55. data/lib/cocoapods/command/linter.rb +0 -317
  56. data/lib/cocoapods/command/update.rb +0 -25
  57. data/lib/cocoapods/dependency.rb +0 -285
  58. data/lib/cocoapods/downloader/git.rb +0 -276
  59. data/lib/cocoapods/downloader/http.rb +0 -99
  60. data/lib/cocoapods/downloader/mercurial.rb +0 -26
  61. data/lib/cocoapods/downloader/subversion.rb +0 -42
  62. data/lib/cocoapods/local_pod.rb +0 -620
  63. data/lib/cocoapods/lockfile.rb +0 -274
  64. data/lib/cocoapods/platform.rb +0 -127
  65. data/lib/cocoapods/podfile.rb +0 -551
  66. data/lib/cocoapods/source.rb +0 -223
  67. data/lib/cocoapods/specification.rb +0 -579
  68. data/lib/cocoapods/specification/set.rb +0 -175
  69. data/lib/cocoapods/specification/statistics.rb +0 -112
  70. data/lib/cocoapods/user_interface/ui_pod.rb +0 -130
  71. data/lib/cocoapods/version.rb +0 -26
@@ -1,79 +1,232 @@
1
- require 'pathname'
2
-
3
1
  module Pod
2
+
3
+ # Stores the global configuration of CocoaPods.
4
+ #
4
5
  class Config
5
- def self.instance
6
- @instance ||= new
7
- end
8
6
 
9
- def self.instance=(instance)
10
- @instance = instance
11
- end
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
+ # generate_docs: false
15
+ # install_docs: false
16
+ #
17
+ DEFAULTS = {
18
+ :verbose => false,
19
+ :silent => false,
20
+ :skip_repo_update => false,
21
+ :aggressive_cache => false,
22
+
23
+ :clean => true,
24
+ :generate_docs => true,
25
+ :install_docs => true,
26
+ :integrate_targets => true,
27
+ :skip_repo_update => true,
28
+ :new_version_message => true,
29
+ }
30
+
31
+ #--------------------------------------#
32
+
33
+ # @!group UI
34
+
35
+ # @return [Bool] Whether CocoaPods should provide detailed output about the
36
+ # performed actions.
37
+ #
38
+ attr_accessor :verbose
39
+ alias_method :verbose?, :verbose
40
+
41
+ # @return [Bool] Whether CocoaPods should produce not output.
42
+ #
43
+ attr_accessor :silent
44
+ alias_method :silent?, :silent
45
+
46
+ # @return [Bool] Whether the generated documentation should be installed to
47
+ # Xcode.
48
+ #
49
+ attr_accessor :new_version_message
50
+ alias_method :new_version_message?, :new_version_message
51
+
52
+ #--------------------------------------#
12
53
 
13
- attr_accessor :repos_dir, :project_root, :project_pods_root
14
- attr_accessor :clean, :verbose, :silent
15
- attr_accessor :generate_docs, :doc_install
54
+ # @!group Installation
55
+
56
+ # @return [Bool] Whether the installer should clean after the installation.
57
+ #
58
+ attr_accessor :clean
59
+ alias_method :clean?, :clean
60
+
61
+ # @return [Bool] Whether the documentation should be generated for the
62
+ # installed Pods.
63
+ #
64
+ attr_accessor :generate_docs
65
+ alias_method :generate_docs?, :generate_docs
66
+
67
+ # @return [Bool] Whether the generated documentation should be installed to
68
+ # Xcode.
69
+ #
70
+ attr_accessor :install_docs
71
+ alias_method :install_docs?, :install_docs
72
+
73
+ # @return [Bool] Whether CocoaPods should integrate a user target and build
74
+ # the workspace or just create the Pods project.
75
+ #
16
76
  attr_accessor :integrate_targets
17
- attr_accessor :new_version_message, :skip_repo_update
77
+ alias_method :integrate_targets?, :integrate_targets
18
78
 
19
- alias_method :clean?, :clean
20
- alias_method :verbose?, :verbose
21
- alias_method :silent?, :silent
22
- alias_method :generate_docs?, :generate_docs
23
- alias_method :doc_install?, :doc_install
24
- alias_method :integrate_targets?, :integrate_targets
25
- alias_method :skip_repo_update?, :skip_repo_update
26
- alias_method :new_version_message?, :new_version_message
79
+
80
+ # @return [Bool] Whether the installer should skip the repos update.
81
+ #
82
+ attr_accessor :skip_repo_update
83
+ alias_method :skip_repo_update?, :skip_repo_update
84
+
85
+ # @return [Bool] Whether the downloader should use more aggressive caching
86
+ # options.
87
+ #
88
+ attr_accessor :aggressive_cache
89
+ alias_method :aggressive_cache?, :aggressive_cache
90
+
91
+ #--------------------------------------#
92
+
93
+ # @!group Initialization
27
94
 
28
95
  def initialize
29
- @repos_dir = Pathname.new(File.expand_path("~/.cocoapods"))
30
- @verbose = @silent = @skip_repo_update = false
31
- @clean = @generate_docs = @doc_install = @integrate_targets = @new_version_message = true
96
+ configure_with(DEFAULTS)
97
+
98
+ if user_settings_file.exist?
99
+ require 'yaml'
100
+ user_settings = YAML.load_file(user_settings_file)
101
+ configure_with(user_settings)
102
+ end
32
103
  end
33
104
 
34
- def project_root
35
- @project_root ||= Pathname.pwd
105
+ def verbose
106
+ @verbose && !silent
36
107
  end
37
108
 
38
- def project_pods_root
39
- @project_pods_root ||= project_root + 'Pods'
109
+ #--------------------------------------#
110
+
111
+ # @!group Paths
112
+
113
+ # @return [Pathname] the directory where the CocoaPods sources are stored.
114
+ #
115
+ def repos_dir
116
+ @repos_dir ||= Pathname.new(ENV['HOME'] + "/.cocoapods")
40
117
  end
41
118
 
42
- def project_podfile
43
- unless @project_podfile
44
- @project_podfile = project_root + 'CocoaPods.podfile'
45
- unless @project_podfile.exist?
46
- @project_podfile = project_root + 'Podfile'
47
- end
48
- end
49
- @project_podfile
119
+ attr_writer :repos_dir
120
+
121
+ # @return [Pathname] the root of the CocoaPods installation where the
122
+ # Podfile is located.
123
+ #
124
+ def installation_root
125
+ @installation_root ||= Pathname.pwd
50
126
  end
51
127
 
52
- def project_lockfile
53
- @project_lockfile ||= project_root + 'Podfile.lock'
128
+ attr_writer :installation_root
129
+ alias :project_root :installation_root
130
+
131
+ # @return [Pathname] The root of the sandbox.
132
+ #
133
+ def sandbox_root
134
+ @sandbox_root ||= installation_root + 'Pods'
54
135
  end
55
136
 
56
- def headers_symlink_root
57
- @headers_symlink_root ||= "#{project_pods_root}/Headers"
137
+ attr_writer :sandbox_root
138
+ alias :project_pods_root :sandbox_root
139
+
140
+ # @return [Sandbox] The sandbox of the current project.
141
+ #
142
+ def sandbox
143
+ @sandbox ||= Sandbox.new(sandbox_root)
58
144
  end
59
145
 
60
146
  # @return [Podfile] The Podfile to use for the current execution.
61
147
  #
62
148
  def podfile
63
- @podfile ||= begin
64
- Podfile.from_file(project_podfile) if project_podfile.exist?
65
- end
149
+ @podfile ||= Podfile.from_file(podfile_path) if podfile_path.exist?
66
150
  end
67
151
  attr_writer :podfile
68
152
 
69
153
  # @return [Lockfile] The Lockfile to use for the current execution.
70
154
  #
71
155
  def lockfile
72
- @lockfile ||= begin
73
- Lockfile.from_file(project_lockfile) if project_lockfile.exist?
156
+ @lockfile ||= Lockfile.from_file(lockfile_path) if lockfile_path.exist?
157
+ end
158
+
159
+ #--------------------------------------#
160
+
161
+ # @!group Helpers
162
+
163
+ # private
164
+
165
+ # @return [Pathname] The path of the file which contains the user settings.
166
+ #
167
+ def user_settings_file
168
+ Pathname.new(ENV['HOME'] + "/.cocoapods/config.yaml")
169
+ end
170
+
171
+ # Sets the values of the attributes with the given hash.
172
+ #
173
+ # @param [Hash{String,Symbol => Object}] values_by_key
174
+ # The values of the attributes grouped by key.
175
+ #
176
+ # @return [void]
177
+ #
178
+ def configure_with(values_by_key)
179
+ values_by_key.each do |key, value|
180
+ self.instance_variable_set("@#{key}", value)
74
181
  end
75
182
  end
76
183
 
184
+ # Returns the path of the Podfile.
185
+ #
186
+ # @note The Podfile can be named either `CocoaPods.podfile` or `Podfile`.
187
+ # The first is preferred as it allows to specify an OS X UTI.
188
+ #
189
+ def podfile_path
190
+ unless @podfile_path
191
+ path = installation_root + 'Podfile.yaml'
192
+ path = installation_root + 'Podfile' unless path.exist?
193
+ @podfile_path = path
194
+ end
195
+ @podfile_path
196
+ end
197
+
198
+ # Returns the path of the Lockfile.
199
+ #
200
+ # @note The Lockfile is named `Podfile.lock`.
201
+ #
202
+ def lockfile_path
203
+ @lockfile_path ||= installation_root + 'Podfile.lock'
204
+ end
205
+
206
+ #--------------------------------------#
207
+
208
+ # @return [Config] the current config instance creating one if needed.
209
+ #
210
+ def self.instance
211
+ @instance ||= new
212
+ end
213
+
214
+ # Sets the current config instance. If set to nil the config will be
215
+ # recreated when needed.
216
+ #
217
+ # @param [Config, Nil] the instance.
218
+ #
219
+ # @return [void]
220
+ #
221
+ def self.instance=(instance)
222
+ @instance = instance
223
+ end
224
+
225
+ #-------------------------------------------------------------------------#
226
+
227
+ # Provides support for accessing the configuration instance in other
228
+ # scopes.
229
+ #
77
230
  module Mixin
78
231
  def config
79
232
  Config.instance
@@ -1,45 +1,58 @@
1
- require 'uri'
1
+ require 'cocoapods-downloader'
2
2
 
3
3
  module Pod
4
- class Downloader
5
- autoload :Git, 'cocoapods/downloader/git'
6
- autoload :GitHub, 'cocoapods/downloader/git'
7
- autoload :Mercurial, 'cocoapods/downloader/mercurial'
8
- autoload :Subversion, 'cocoapods/downloader/subversion'
9
- autoload :Http, 'cocoapods/downloader/http'
4
+ module Downloader
5
+ class Base
10
6
 
11
- extend Executable
7
+ override_api do
12
8
 
13
- def self.for_pod(pod)
14
- spec = pod.top_specification
15
- for_target(pod.root, spec.source.dup)
16
- end
17
-
18
- attr_reader :target_path, :url, :options
9
+ def execute_command(executable, command, raise_on_failure = false)
10
+ Executable.execute_command(executable, command, raise_on_failure)
11
+ end
19
12
 
20
- def initialize(target_path, url, options)
21
- @target_path, @url, @options = target_path, url, options
22
- @target_path.mkpath
23
- end
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
24
28
 
25
- private
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
26
44
 
27
- def self.for_target(target_path, options)
28
- options = options.dup
29
- if url = options.delete(:git)
30
- if url.to_s =~ /github.com/
31
- GitHub.new(target_path, url, options)
32
- else
33
- Git.new(target_path, url, options)
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
34
54
  end
35
- elsif url = options.delete(:hg)
36
- Mercurial.new(target_path, url, options)
37
- elsif url = options.delete(:svn)
38
- Subversion.new(target_path, url, options)
39
- elsif url = options.delete(:http)
40
- Http.new(target_path, url, options)
41
- else
42
- raise "Unsupported download strategy `#{options.inspect}'."
55
+
43
56
  end
44
57
  end
45
58
  end
@@ -1,61 +1,118 @@
1
- require 'open4'
2
-
3
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
+ #
4
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
+ #
5
87
  class Indenter < ::Array
6
- include Config::Mixin
7
88
 
89
+ # @return [Fixnum] The indentation level of the UI.
90
+ #
8
91
  attr_accessor :indent
92
+
93
+ # @return [IO] the {IO} to which the output should be printed.
94
+ #
9
95
  attr_accessor :io
10
96
 
97
+ # @param [IO] io @see io
98
+ #
11
99
  def initialize(io = nil)
12
100
  @io = io
13
101
  @indent = ' ' * UI.indentation_level
14
102
  end
15
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
+ #
16
111
  def <<(value)
17
112
  super
18
113
  ensure
19
114
  @io << "#{ indent }#{ value }" if @io
20
115
  end
21
116
  end
22
-
23
- def executable(name)
24
- bin = `which #{name}`.strip
25
- base_method = "base_" << name.to_s
26
- define_method(base_method) do |command, should_raise|
27
- if bin.empty?
28
- raise Informative, "Unable to locate the executable `#{name}'"
29
- end
30
- full_command = "#{bin} #{command}"
31
- if Config.instance.verbose?
32
- UI.message("$ #{full_command}")
33
- stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
34
- else
35
- stdout, stderr = Indenter.new, Indenter.new
36
- end
37
- status = Open4.spawn(full_command, :stdout => stdout, :stderr => stderr, :status => true)
38
-
39
- output = stdout.join("\n") + stderr.join("\n") # TODO will this suffice?
40
- unless status.success?
41
- if should_raise
42
- raise Informative, "#{name} #{command}\n\n#{output}"
43
- else
44
- UI.message("[!] Failed: #{full_command}".red)
45
- end
46
- end
47
- output
48
- end
49
-
50
- define_method(name) do |command|
51
- send(base_method, command, false)
52
- end
53
-
54
- define_method(name.to_s + "!") do |command|
55
- send(base_method, command, true)
56
- end
57
-
58
- private name
59
- end
60
117
  end
61
118
  end