cocoapods 0.16.4 → 0.17.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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