cocoapods 1.6.2 → 1.7.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -7
  3. data/README.md +9 -9
  4. data/lib/cocoapods.rb +2 -0
  5. data/lib/cocoapods/command.rb +1 -1
  6. data/lib/cocoapods/command/init.rb +2 -12
  7. data/lib/cocoapods/command/install.rb +3 -0
  8. data/lib/cocoapods/command/lib/create.rb +1 -1
  9. data/lib/cocoapods/command/lib/lint.rb +5 -1
  10. data/lib/cocoapods/command/list.rb +3 -5
  11. data/lib/cocoapods/command/repo.rb +1 -0
  12. data/lib/cocoapods/command/repo/add.rb +4 -5
  13. data/lib/cocoapods/command/repo/add_cdn.rb +58 -0
  14. data/lib/cocoapods/command/repo/list.rb +5 -6
  15. data/lib/cocoapods/command/repo/push.rb +6 -5
  16. data/lib/cocoapods/command/spec/create.rb +12 -12
  17. data/lib/cocoapods/command/spec/lint.rb +1 -1
  18. data/lib/cocoapods/command/update.rb +3 -0
  19. data/lib/cocoapods/config.rb +1 -0
  20. data/lib/cocoapods/executable.rb +32 -7
  21. data/lib/cocoapods/gem_version.rb +1 -1
  22. data/lib/cocoapods/generator/app_target_helper.rb +1 -1
  23. data/lib/cocoapods/generator/embed_frameworks_script.rb +13 -0
  24. data/lib/cocoapods/generator/file_list.rb +39 -0
  25. data/lib/cocoapods/generator/module_map.rb +1 -1
  26. data/lib/cocoapods/installer.rb +188 -46
  27. data/lib/cocoapods/installer/analyzer.rb +64 -39
  28. data/lib/cocoapods/installer/analyzer/pod_variant.rb +14 -9
  29. data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +11 -2
  30. data/lib/cocoapods/installer/installation_options.rb +70 -44
  31. data/lib/cocoapods/installer/pod_source_installer.rb +9 -4
  32. data/lib/cocoapods/installer/podfile_validator.rb +9 -0
  33. data/lib/cocoapods/installer/post_install_hooks_context.rb +5 -2
  34. data/lib/cocoapods/installer/project_cache/project_cache.rb +11 -0
  35. data/lib/cocoapods/installer/project_cache/project_cache_analysis_result.rb +53 -0
  36. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +156 -0
  37. data/lib/cocoapods/installer/project_cache/project_cache_version.rb +43 -0
  38. data/lib/cocoapods/installer/project_cache/project_installation_cache.rb +77 -0
  39. data/lib/cocoapods/installer/project_cache/project_metadata_cache.rb +63 -0
  40. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +134 -0
  41. data/lib/cocoapods/installer/project_cache/target_metadata.rb +70 -0
  42. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +89 -0
  43. data/lib/cocoapods/installer/sandbox_header_paths_installer.rb +45 -0
  44. data/lib/cocoapods/installer/target_uuid_generator.rb +32 -0
  45. data/lib/cocoapods/installer/user_project_integrator.rb +8 -6
  46. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +128 -63
  47. data/lib/cocoapods/installer/xcode.rb +3 -0
  48. data/lib/cocoapods/installer/xcode/multi_pods_project_generator.rb +72 -0
  49. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +102 -218
  50. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +75 -0
  51. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +1 -1
  52. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +29 -17
  53. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +31 -65
  54. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +155 -0
  55. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +265 -110
  56. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +70 -43
  57. data/lib/cocoapods/installer/xcode/pods_project_generator/pods_project_writer.rb +75 -0
  58. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +119 -0
  59. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +44 -7
  60. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +5 -7
  61. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +32 -0
  62. data/lib/cocoapods/installer/xcode/pods_project_generator_result.rb +35 -0
  63. data/lib/cocoapods/installer/xcode/single_pods_project_generator.rb +38 -0
  64. data/lib/cocoapods/installer/xcode/target_validator.rb +32 -25
  65. data/lib/cocoapods/native_target_extension.rb +54 -0
  66. data/lib/cocoapods/open-uri.rb +1 -1
  67. data/lib/cocoapods/podfile.rb +13 -0
  68. data/lib/cocoapods/project.rb +88 -10
  69. data/lib/cocoapods/resolver.rb +11 -8
  70. data/lib/cocoapods/resolver/resolver_specification.rb +7 -7
  71. data/lib/cocoapods/sandbox.rb +38 -9
  72. data/lib/cocoapods/sandbox/file_accessor.rb +21 -0
  73. data/lib/cocoapods/sandbox/headers_store.rb +18 -3
  74. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +1 -14
  75. data/lib/cocoapods/sources_manager.rb +11 -3
  76. data/lib/cocoapods/target.rb +67 -7
  77. data/lib/cocoapods/target/aggregate_target.rb +70 -8
  78. data/lib/cocoapods/target/build_settings.rb +124 -65
  79. data/lib/cocoapods/target/build_type.rb +139 -0
  80. data/lib/cocoapods/target/framework_paths.rb +12 -7
  81. data/lib/cocoapods/target/pod_target.rb +322 -65
  82. data/lib/cocoapods/user_interface.rb +2 -2
  83. data/lib/cocoapods/user_interface/error_report.rb +3 -0
  84. data/lib/cocoapods/user_interface/inspector_reporter.rb +1 -1
  85. data/lib/cocoapods/validator.rb +74 -39
  86. data/lib/cocoapods/version_metadata.rb +7 -0
  87. metadata +30 -6
@@ -51,17 +51,17 @@ module Pod
51
51
  # @todo The template is outdated.
52
52
 
53
53
  def default_data_for_template(name)
54
- data = {}
55
- data[:name] = name
56
- data[:version] = '0.0.1'
57
- data[:summary] = "A short description of #{name}."
58
- data[:homepage] = "http://EXAMPLE/#{name}"
59
- data[:author_name] = `git config --get user.name`.strip
60
- data[:author_email] = `git config --get user.email`.strip
61
- data[:source_url] = "http://EXAMPLE/#{name}.git"
62
- data[:ref_type] = ':tag'
63
- data[:ref] = '#{spec.version}'
64
- data
54
+ {
55
+ :name => name,
56
+ :version => '0.0.1',
57
+ :summary => "A short description of #{name}.",
58
+ :homepage => "http://EXAMPLE/#{name}",
59
+ :author_name => Executable.capture_command('git', %w(config --get user.name), :capture => :out).first.strip,
60
+ :author_email => Executable.capture_command('git', %w(config --get user.email), :capture => :out).first.strip,
61
+ :source_url => "http://EXAMPLE/#{name}.git",
62
+ :ref_type => ':tag',
63
+ :ref => '#{spec.version}',
64
+ }
65
65
  end
66
66
 
67
67
  def github_data_for_template(repo_id)
@@ -112,7 +112,7 @@ module Pod
112
112
  # Be sure to run `pod spec lint #{data[:name]}.podspec' to ensure this is a
113
113
  # valid spec and to remove all comments including this before submitting the spec.
114
114
  #
115
- # To learn more about Podspec attributes see https://docs.cocoapods.org/specification.html
115
+ # To learn more about Podspec attributes see https://guides.cocoapods.org/syntax/podspec.html
116
116
  # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
117
117
  #
118
118
 
@@ -32,7 +32,7 @@ module Pod
32
32
  'Multiple platforms must be comma-delimited'],
33
33
  ['--private', 'Lint skips checks that apply only to public specs'],
34
34
  ['--swift-version=VERSION', 'The SWIFT_VERSION that should be used to lint the spec. ' \
35
- 'This takes precedence over a .swift-version file.'],
35
+ 'This takes precedence over the Swift versions specified by the spec or a `.swift-version` file.'],
36
36
  ['--skip-import-validation', 'Lint skips validating that the pod can be imported'],
37
37
  ['--skip-tests', 'Lint skips building and running tests during validation'],
38
38
  ].concat(super)
@@ -24,6 +24,7 @@ module Pod
24
24
  ['--sources=https://github.com/artsy/Specs,master', 'The sources from which to update dependent pods. ' \
25
25
  'Multiple sources must be comma-delimited. The master repo will not be included by default with this option.'],
26
26
  ['--exclude-pods=podName', 'Pods to exclude during update. Multiple pods must be comma-delimited.'],
27
+ ['--clean-install', 'Ignore the contents of the project cache and force a full pod installation. This only applies to projects that have enabled incremental installation.'],
27
28
  ].concat(super)
28
29
  end
29
30
 
@@ -32,6 +33,7 @@ module Pod
32
33
 
33
34
  source_urls = argv.option('sources', '').split(',')
34
35
  excluded_pods = argv.option('exclude-pods', '').split(',')
36
+ @clean_install = argv.flag?('clean-install', false)
35
37
  unless source_urls.empty?
36
38
  source_pods = source_urls.flat_map { |url| config.sources_manager.source_with_name_or_url(url).pods }
37
39
  unless source_pods.empty?
@@ -86,6 +88,7 @@ module Pod
86
88
 
87
89
  installer = installer_for_config
88
90
  installer.repo_update = repo_update?(:default => true)
91
+ installer.clean_install = @clean_install
89
92
  if @pods
90
93
  verify_lockfile_exists!
91
94
  verify_pods_are_installed!
@@ -290,6 +290,7 @@ module Pod
290
290
  'CocoaPods.podfile.yaml',
291
291
  'CocoaPods.podfile',
292
292
  'Podfile',
293
+ 'Podfile.rb',
293
294
  ].freeze
294
295
 
295
296
  public
@@ -49,6 +49,10 @@ module Pod
49
49
  bin = which!(executable)
50
50
 
51
51
  command = command.map(&:to_s)
52
+ if File.basename(bin) == 'tar.exe'
53
+ # Tar on Windows needs --force-local
54
+ command.push('--force-local')
55
+ end
52
56
  full_command = "#{bin} #{command.join(' ')}"
53
57
 
54
58
  if Config.instance.verbose?
@@ -91,6 +95,9 @@ module Pod
91
95
  paths.uniq!
92
96
  paths.each do |path|
93
97
  bin = File.expand_path(program, path)
98
+ if Gem.win_platform?
99
+ bin += '.exe'
100
+ end
94
101
  if File.file?(bin) && File.executable?(bin)
95
102
  return bin
96
103
  end
@@ -114,7 +121,7 @@ module Pod
114
121
 
115
122
  # Runs the given command, capturing the desired output.
116
123
  #
117
- # @param [String] bin
124
+ # @param [String] executable
118
125
  # The binary to use.
119
126
  #
120
127
  # @param [Array<#to_s>] command
@@ -123,23 +130,41 @@ module Pod
123
130
  # @param [Symbol] capture
124
131
  # Whether it should raise if the command fails.
125
132
  #
133
+ # @param [Hash] env
134
+ # Environment variables to be set for the command.
135
+ #
126
136
  # @raise If the executable could not be located.
127
137
  #
128
138
  # @return [(String, Process::Status)]
129
139
  # The desired captured output from the command, and the status from
130
140
  # running the command.
131
141
  #
132
- def self.capture_command(executable, command, capture: :merge)
142
+ def self.capture_command(executable, command, capture: :merge, env: {}, **kwargs)
133
143
  bin = which!(executable)
134
144
 
135
145
  require 'open3'
136
146
  command = command.map(&:to_s)
137
147
  case capture
138
- when :merge then Open3.capture2e(bin, *command)
139
- when :both then Open3.capture3(bin, *command)
140
- when :out then Open3.capture3(bin, *command).values_at(0, -1)
141
- when :err then Open3.capture3(bin, *command).drop(1)
142
- when :none then Open3.capture3(bin, *command).last
148
+ when :merge then Open3.capture2e(env, [bin, bin], *command, **kwargs)
149
+ when :both then Open3.capture3(env, [bin, bin], *command, **kwargs)
150
+ when :out then Open3.capture3(env, [bin, bin], *command, **kwargs).values_at(0, -1)
151
+ when :err then Open3.capture3(env, [bin, bin], *command, **kwargs).drop(1)
152
+ when :none then Open3.capture3(env, [bin, bin], *command, **kwargs).last
153
+ end
154
+ end
155
+
156
+ # (see Executable.capture_command)
157
+ #
158
+ # @raise If running the command fails
159
+ #
160
+ def self.capture_command!(executable, command, **kwargs)
161
+ capture_command(executable, command, **kwargs).tap do |result|
162
+ result = Array(result)
163
+ status = result.last
164
+ unless status.success?
165
+ output = result[0..-2].join
166
+ raise Informative, "#{bin} #{command.join(' ')}\n\n#{output}".strip
167
+ end
143
168
  end
144
169
  end
145
170
 
@@ -1,5 +1,5 @@
1
1
  module Pod
2
2
  # The version of the CocoaPods command line tool.
3
3
  #
4
- VERSION = '1.6.2'.freeze unless defined? Pod::VERSION
4
+ VERSION = '1.7.0.beta.1'.freeze unless defined? Pod::VERSION
5
5
  end
@@ -260,7 +260,7 @@ module Pod
260
260
 
261
261
  @implementation CPTestAppHostAppDelegate
262
262
 
263
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
263
+ - (BOOL)application:(UIApplication *)__unused application didFinishLaunchingWithOptions:(NSDictionary *)__unused launchOptions
264
264
  {
265
265
  self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
266
266
  self.window.rootViewController = [UIViewController new];
@@ -154,6 +154,14 @@ module Pod
154
154
  fi
155
155
  }
156
156
 
157
+ # Copies the bcsymbolmap files of a vendored framework
158
+ install_bcsymbolmap() {
159
+ local bcsymbolmap_path = "$1"
160
+ local destination="${TARGET_BUILD_DIR}"
161
+ echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${bcsymbolmap_path}\" \"${destination}\""
162
+ rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"
163
+ }
164
+
157
165
  # Signs a framework with the provided identity
158
166
  code_sign_if_enabled() {
159
167
  if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
@@ -206,6 +214,11 @@ module Pod
206
214
  # Vendored frameworks might have a dSYM file next to them so ensure its copied. Frameworks built from
207
215
  # sources will have their dSYM generated and copied by Xcode.
208
216
  script << %( install_dsym "#{framework_with_dsym.dsym_path}"\n) unless framework_with_dsym.dsym_path.nil?
217
+ unless framework_with_dsym.bcsymbolmap_paths.nil?
218
+ framework_with_dsym.bcsymbolmap_paths.each do |bcsymbolmap_path|
219
+ script << %( install_bcsymbolmap "#{bcsymbolmap_path}"\n)
220
+ end
221
+ end
209
222
  end
210
223
  script << "fi\n"
211
224
  end
@@ -0,0 +1,39 @@
1
+ module Pod
2
+ module Generator
3
+ # Generates an xcfilelist file.
4
+ #
5
+ class FileList
6
+ # @return [Array<String>] The paths of the files in the file list.
7
+ #
8
+ attr_reader :paths
9
+
10
+ # Initialize a new instance
11
+ #
12
+ # @param [Array<String>] paths
13
+ # @see paths
14
+ #
15
+ def initialize(paths)
16
+ @paths = paths
17
+ end
18
+
19
+ # Generates the contents of the file list.
20
+ #
21
+ # @return [String]
22
+ #
23
+ def generate
24
+ paths.join("\n")
25
+ end
26
+
27
+ # Generates and saves the file list to the given path.
28
+ #
29
+ # @param [Pathname] path
30
+ # The path where the file list should be stored.
31
+ #
32
+ # @return [void]
33
+ #
34
+ def save_as(path)
35
+ path.open('w') { |file_list| file_list.write(generate) }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -82,7 +82,7 @@ module Pod
82
82
  # Ensures that only framework targets have `framework` prepended.
83
83
  #
84
84
  def module_specifier_prefix
85
- if target.requires_frameworks?
85
+ if target.build_as_framework?
86
86
  'framework '
87
87
  else
88
88
  ''
@@ -1,5 +1,6 @@
1
1
  require 'active_support/core_ext/string/inflections'
2
2
  require 'fileutils'
3
+ require 'cocoapods/podfile'
3
4
 
4
5
  module Pod
5
6
  # The Installer is responsible of taking a Podfile and transform it in the
@@ -29,21 +30,22 @@ module Pod
29
30
  # source control.
30
31
  #
31
32
  class Installer
32
- autoload :Analyzer, 'cocoapods/installer/analyzer'
33
- autoload :InstallationOptions, 'cocoapods/installer/installation_options'
34
- autoload :PostInstallHooksContext, 'cocoapods/installer/post_install_hooks_context'
35
- autoload :PreInstallHooksContext, 'cocoapods/installer/pre_install_hooks_context'
36
- autoload :SourceProviderHooksContext, 'cocoapods/installer/source_provider_hooks_context'
37
- autoload :PodfileValidator, 'cocoapods/installer/podfile_validator'
38
- autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
39
- autoload :PodSourcePreparer, 'cocoapods/installer/pod_source_preparer'
40
- autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
41
- autoload :Xcode, 'cocoapods/installer/xcode'
33
+ autoload :Analyzer, 'cocoapods/installer/analyzer'
34
+ autoload :InstallationOptions, 'cocoapods/installer/installation_options'
35
+ autoload :PostInstallHooksContext, 'cocoapods/installer/post_install_hooks_context'
36
+ autoload :PreInstallHooksContext, 'cocoapods/installer/pre_install_hooks_context'
37
+ autoload :SourceProviderHooksContext, 'cocoapods/installer/source_provider_hooks_context'
38
+ autoload :PodfileValidator, 'cocoapods/installer/podfile_validator'
39
+ autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
40
+ autoload :PodSourcePreparer, 'cocoapods/installer/pod_source_preparer'
41
+ autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
42
+ autoload :Xcode, 'cocoapods/installer/xcode'
43
+ autoload :SandboxHeaderPathsInstaller, 'cocoapods/installer/sandbox_header_paths_installer'
44
+ autoload :SandboxDirCleaner, 'cocoapods/installer/sandbox_dir_cleaner'
45
+ autoload :ProjectCache, 'cocoapods/installer/project_cache/project_cache'
46
+ autoload :TargetUUIDGenerator, 'cocoapods/installer/target_uuid_generator'
42
47
 
43
48
  include Config::Mixin
44
- include InstallationOptions::Mixin
45
-
46
- delegate_installation_options { podfile }
47
49
 
48
50
  # @return [Sandbox] The sandbox where the Pods should be installed.
49
51
  #
@@ -104,6 +106,12 @@ module Pod
104
106
  attr_accessor :deployment
105
107
  alias_method :deployment?, :deployment
106
108
 
109
+ # @return [Boolean] Whether installation should ignore the contents of the project cache
110
+ # when incremental installation is enabled.
111
+ #
112
+ attr_accessor :clean_install
113
+ alias_method :clean_install?, :clean_install
114
+
107
115
  #-------------------------------------------------------------------------#
108
116
 
109
117
  private
@@ -113,6 +121,18 @@ module Pod
113
121
  #
114
122
  attr_reader :pod_installers
115
123
 
124
+ # @return [ProjectInstallationCache] The installation cache stored in Pods/.project_cache/installation_cache
125
+ #
126
+ attr_reader :installation_cache
127
+
128
+ # @return [ProjectMetadataCache] The metadata cache stored in Pods/.project_cache/metadata_cache
129
+ #
130
+ attr_reader :metadata_cache
131
+
132
+ # @return [ProjectCacheVersion] The version of the project cache stored in Pods/.project_cache/version
133
+ #
134
+ attr_reader :project_cache_version
135
+
116
136
  #-------------------------------------------------------------------------#
117
137
 
118
138
  public
@@ -145,6 +165,33 @@ module Pod
145
165
  perform_post_install_actions
146
166
  end
147
167
 
168
+ def analyze_project_cache
169
+ user_projects = aggregate_targets.map(&:user_project).compact
170
+ object_version = user_projects.min_by { |p| p.object_version.to_i }.object_version.to_i unless user_projects.empty?
171
+
172
+ if !installation_options.incremental_installation
173
+ # Run entire installation.
174
+ ProjectCache::ProjectCacheAnalysisResult.new(pod_targets, aggregate_targets, {},
175
+ analysis_result.all_user_build_configurations, object_version)
176
+ else
177
+ UI.message 'Analyzing Project Cache' do
178
+ @installation_cache = ProjectCache::ProjectInstallationCache.from_file(sandbox.project_installation_cache_path)
179
+ @metadata_cache = ProjectCache::ProjectMetadataCache.from_file(sandbox.project_metadata_cache_path)
180
+ @project_cache_version = ProjectCache::ProjectCacheVersion.from_file(sandbox.project_version_cache_path)
181
+
182
+ force_clean_install = clean_install || project_cache_version.version != Version.create(VersionMetadata.gem_version)
183
+ cache_result = ProjectCache::ProjectCacheAnalyzer.new(sandbox, installation_cache, analysis_result.all_user_build_configurations,
184
+ object_version, pod_targets, aggregate_targets, :clean_install => force_clean_install).analyze
185
+ aggregate_targets_to_generate = cache_result.aggregate_targets_to_generate || []
186
+ pod_targets_to_generate = cache_result.pod_targets_to_generate
187
+ (aggregate_targets_to_generate + pod_targets_to_generate).each do |target|
188
+ UI.message "- Regenerating #{target.label}"
189
+ end
190
+ cache_result
191
+ end
192
+ end
193
+ end
194
+
148
195
  def prepare
149
196
  # Raise if pwd is inside Pods
150
197
  if Dir.pwd.start_with?(sandbox.root.to_path)
@@ -173,7 +220,6 @@ module Pod
173
220
  UI.section 'Analyzing dependencies' do
174
221
  analyze(analyzer)
175
222
  validate_build_configurations
176
- clean_sandbox
177
223
  end
178
224
 
179
225
  UI.section 'Verifying no changes' do
@@ -192,29 +238,99 @@ module Pod
192
238
  end
193
239
  end
194
240
 
241
+ # Stages the sandbox after analysis.
242
+ #
243
+ # @param [Sandbox] sandbox
244
+ # The sandbox to stage.
245
+ #
246
+ # @param [Array<PodTarget>] pod_targets
247
+ # The list of all pod targets.
248
+ #
249
+ # @return [void]
250
+ #
251
+ def stage_sandbox(sandbox, pod_targets)
252
+ SandboxHeaderPathsInstaller.new(sandbox, pod_targets).install!
253
+ end
254
+
195
255
  #-------------------------------------------------------------------------#
196
256
 
197
257
  # @!group Pods Project Generation
198
258
 
199
259
  private
200
260
 
201
- def create_generator
202
- Xcode::PodsProjectGenerator.new(sandbox, aggregate_targets, pod_targets, analysis_result, installation_options, config)
261
+ def create_generator(pod_targets_to_generate, aggregate_targets_to_generate, build_configurations, project_object_version, generate_multiple_pod_projects = false)
262
+ if generate_multiple_pod_projects
263
+ Xcode::MultiPodsProjectGenerator.new(sandbox, aggregate_targets_to_generate, pod_targets_to_generate,
264
+ build_configurations, installation_options, config, project_object_version, metadata_cache)
265
+ else
266
+ Xcode::SinglePodsProjectGenerator.new(sandbox, aggregate_targets_to_generate, pod_targets_to_generate, build_configurations, installation_options, config, project_object_version)
267
+ end
203
268
  end
204
269
 
205
- # Generate the 'Pods/Pods.xcodeproj' project.
270
+ # Generates the Xcode project(s) that go inside the `Pods/` directory.
206
271
  #
207
- def generate_pods_project(generator = create_generator)
272
+ def generate_pods_project
273
+ stage_sandbox(sandbox, pod_targets)
274
+
275
+ cache_analysis_result = analyze_project_cache
276
+ pod_targets_to_generate = cache_analysis_result.pod_targets_to_generate
277
+ aggregate_targets_to_generate = cache_analysis_result.aggregate_targets_to_generate
278
+
279
+ clean_sandbox(pod_targets_to_generate)
280
+
281
+ create_and_save_projects(pod_targets_to_generate, aggregate_targets_to_generate,
282
+ cache_analysis_result.build_configurations, cache_analysis_result.project_object_version)
283
+ SandboxDirCleaner.new(sandbox, pod_targets, aggregate_targets).clean!
284
+
285
+ update_project_cache(cache_analysis_result, target_installation_results)
286
+ write_lockfiles
287
+ end
288
+
289
+ def create_and_save_projects(pod_targets_to_generate, aggregate_targets_to_generate, build_configurations, project_object_version)
208
290
  UI.section 'Generating Pods project' do
209
- @target_installation_results = generator.generate!
210
- @pods_project = generator.project
291
+ generator = create_generator(pod_targets_to_generate, aggregate_targets_to_generate,
292
+ build_configurations, project_object_version,
293
+ installation_options.generate_multiple_pod_projects)
294
+
295
+ pod_project_generation_result = generator.generate!
296
+ @target_installation_results = pod_project_generation_result.target_installation_results
297
+ @pods_project = pod_project_generation_result.project
298
+ # The `pod_target_subprojects` is used for backwards compatibility so that consumers can iterate over
299
+ # all pod targets across projects without needing to open each one.
300
+ @pod_target_subprojects = pod_project_generation_result.projects_by_pod_targets.keys
301
+ @generated_projects = ([pods_project] + pod_target_subprojects || []).compact
302
+ @generated_pod_targets = pod_targets_to_generate
303
+ @generated_aggregate_targets = aggregate_targets_to_generate || []
304
+ projects_by_pod_targets = pod_project_generation_result.projects_by_pod_targets
305
+
306
+ predictabilize_uuids(generated_projects) if installation_options.deterministic_uuids?
307
+ stabilize_target_uuids(generated_projects)
308
+
211
309
  run_podfile_post_install_hooks
212
- generator.write
213
- generator.share_development_pod_schemes
214
- write_lockfiles
310
+
311
+ projects_writer = Xcode::PodsProjectWriter.new(sandbox, generated_projects,
312
+ target_installation_results.pod_target_installation_results, installation_options)
313
+ projects_writer.write!
314
+
315
+ pods_project_pod_targets = pod_targets_to_generate - projects_by_pod_targets.values.flatten
316
+ all_projects_by_pod_targets = {}
317
+ pods_project_by_targets = { pods_project => pods_project_pod_targets } if pods_project
318
+ all_projects_by_pod_targets.merge!(pods_project_by_targets) if pods_project_by_targets
319
+ all_projects_by_pod_targets.merge!(projects_by_pod_targets) if projects_by_pod_targets
320
+ all_projects_by_pod_targets.each do |project, pod_targets|
321
+ generator.share_development_pod_schemes(project, development_pod_targets(pod_targets))
322
+ end
215
323
  end
216
324
  end
217
325
 
326
+ def predictabilize_uuids(projects)
327
+ UI.message('- Generating deterministic UUIDs') { Xcodeproj::Project.predictabilize_uuids(projects) }
328
+ end
329
+
330
+ def stabilize_target_uuids(projects)
331
+ UI.message('- Stabilizing target UUIDs') { TargetUUIDGenerator.new(projects).generate! }
332
+ end
333
+
218
334
  #-------------------------------------------------------------------------#
219
335
 
220
336
  public
@@ -235,6 +351,10 @@ module Pod
235
351
  #
236
352
  attr_reader :pods_project
237
353
 
354
+ # @return [Array<Pod::Project>] the subprojects nested under pods_project.
355
+ #
356
+ attr_reader :pod_target_subprojects
357
+
238
358
  # @return [Array<AggregateTarget>] The model representations of an
239
359
  # aggregation of pod targets generated for a target definition
240
360
  # in the Podfile as result of the analyzer.
@@ -246,6 +366,18 @@ module Pod
246
366
  #
247
367
  attr_reader :pod_targets
248
368
 
369
+ # @return [Array<Project>] The list of projects generated from the installation.
370
+ #
371
+ attr_reader :generated_projects
372
+
373
+ # @return [Array<PodTarget>] The list of pod targets that were generated from the installation.
374
+ #
375
+ attr_reader :generated_pod_targets
376
+
377
+ # @return [Array<AggregateTarget>] The list of aggregate targets that were generated from the installation.
378
+ #
379
+ attr_reader :generated_aggregate_targets
380
+
249
381
  # @return [Array<Specification>] The specifications that were installed.
250
382
  #
251
383
  attr_accessor :installed_specs
@@ -269,9 +401,7 @@ module Pod
269
401
  end
270
402
 
271
403
  def create_analyzer(plugin_sources = nil)
272
- Analyzer.new(sandbox, podfile, lockfile, plugin_sources, has_dependencies?, update).tap do |analyzer|
273
- analyzer.installation_options = installation_options
274
- end
404
+ Analyzer.new(sandbox, podfile, lockfile, plugin_sources, has_dependencies?, update)
275
405
  end
276
406
 
277
407
  # Ensures that the white-listed build configurations are known to prevent
@@ -295,26 +425,15 @@ module Pod
295
425
  end
296
426
  end
297
427
 
298
- # @return [void] In this step we clean all the folders that will be
299
- # regenerated from scratch and any file which might not be
300
- # overwritten.
428
+ # @return [void] In this step we clean all the header folders for pod targets that will be
429
+ # regenerated from scratch and cleanup any pods that have been removed.
301
430
  #
302
- # @todo [#247] Clean the headers of only the pods to install.
303
- #
304
- def clean_sandbox
305
- sandbox.public_headers.implode!
306
- target_support_dirs = sandbox.target_support_files_root.children.select(&:directory?)
431
+ def clean_sandbox(pod_targets)
307
432
  pod_targets.each do |pod_target|
308
- pod_target.build_headers.implode!
309
- target_support_dirs.delete(pod_target.support_files_dir)
433
+ pod_target.build_headers.implode_path!(pod_target.headers_sandbox)
434
+ sandbox.public_headers.implode_path!(pod_target.headers_sandbox)
310
435
  end
311
436
 
312
- aggregate_targets.each do |aggregate_target|
313
- target_support_dirs.delete(aggregate_target.support_files_dir)
314
- end
315
-
316
- target_support_dirs.each { |dir| FileUtils.rm_rf(dir) }
317
-
318
437
  unless sandbox_state.deleted.empty?
319
438
  title_options = { :verbose_prefix => '-> '.red }
320
439
  sandbox_state.deleted.each do |pod_name|
@@ -497,7 +616,7 @@ module Pod
497
616
  if any_plugin_post_install_hooks?
498
617
  unlock_pod_sources
499
618
 
500
- context = PostInstallHooksContext.generate(sandbox, aggregate_targets)
619
+ context = PostInstallHooksContext.generate(sandbox, pods_project, aggregate_targets)
501
620
  HooksManager.run(:post_install, context, plugins)
502
621
  end
503
622
 
@@ -631,6 +750,21 @@ module Pod
631
750
  end
632
751
  end
633
752
 
753
+ def update_project_cache(cache_analysis_result, target_installation_results)
754
+ return unless installation_cache || metadata_cache
755
+ installation_cache.update_cache_key_by_target_label!(cache_analysis_result.cache_key_by_target_label)
756
+ installation_cache.update_project_object_version!(cache_analysis_result.project_object_version)
757
+ installation_cache.update_build_configurations!(cache_analysis_result.build_configurations)
758
+ installation_cache.save_as(sandbox.project_installation_cache_path)
759
+
760
+ metadata_cache.update_metadata!(target_installation_results.pod_target_installation_results || {},
761
+ target_installation_results.aggregate_target_installation_results || {})
762
+ metadata_cache.save_as(sandbox.project_metadata_cache_path)
763
+
764
+ cache_version = ProjectCache::ProjectCacheVersion.new(VersionMetadata.gem_version)
765
+ cache_version.save_as(sandbox.project_version_cache_path)
766
+ end
767
+
634
768
  # Integrates the user projects adding the dependencies on the CocoaPods
635
769
  # libraries, setting them up to use the xcconfigs and performing other
636
770
  # actions. This step is also responsible of creating the workspace if
@@ -641,7 +775,7 @@ module Pod
641
775
  def integrate_user_project
642
776
  UI.section "Integrating client #{'project'.pluralize(aggregate_targets.map(&:user_project_path).uniq.count)}" do
643
777
  installation_root = config.installation_root
644
- integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, aggregate_targets)
778
+ integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, generated_aggregate_targets, :use_input_output_paths => !installation_options.disable_input_output_paths?)
645
779
  integrator.integrate!
646
780
  end
647
781
  end
@@ -709,11 +843,13 @@ module Pod
709
843
 
710
844
  public
711
845
 
846
+ # @param [Array<PodTarget>] targets
847
+ #
712
848
  # @return [Array<PodTarget>] The targets of the development pods generated by
713
849
  # the installation process. This can be used as a convenience method for external scripts.
714
850
  #
715
- def development_pod_targets
716
- pod_targets.select do |pod_target|
851
+ def development_pod_targets(targets = pod_targets)
852
+ targets.select do |pod_target|
717
853
  sandbox.local?(pod_target.pod_name)
718
854
  end
719
855
  end
@@ -737,6 +873,12 @@ module Pod
737
873
  analysis_result.sandbox_state
738
874
  end
739
875
 
876
+ # @return [InstallationOptions] the installation options to use during install
877
+ #
878
+ def installation_options
879
+ podfile.installation_options
880
+ end
881
+
740
882
  #-------------------------------------------------------------------------#
741
883
 
742
884
  public