cocoapods 1.7.5 → 1.8.0.beta.1

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +175 -11
  3. data/LICENSE +13 -8
  4. data/README.md +2 -1
  5. data/lib/cocoapods/command/init.rb +18 -16
  6. data/lib/cocoapods/command/install.rb +2 -1
  7. data/lib/cocoapods/command/lib/create.rb +1 -2
  8. data/lib/cocoapods/command/lib/lint.rb +12 -11
  9. data/lib/cocoapods/command/repo/add.rb +2 -2
  10. data/lib/cocoapods/command/repo/list.rb +7 -5
  11. data/lib/cocoapods/command/repo/push.rb +15 -12
  12. data/lib/cocoapods/command/setup.rb +2 -88
  13. data/lib/cocoapods/command/spec/lint.rb +10 -9
  14. data/lib/cocoapods/command/update.rb +5 -4
  15. data/lib/cocoapods/config.rb +9 -8
  16. data/lib/cocoapods/external_sources/path_source.rb +1 -1
  17. data/lib/cocoapods/gem_version.rb +1 -1
  18. data/lib/cocoapods/generator/embed_frameworks_script.rb +1 -1
  19. data/lib/cocoapods/generator/info_plist_file.rb +2 -2
  20. data/lib/cocoapods/installer.rb +32 -12
  21. data/lib/cocoapods/installer/analyzer.rb +132 -97
  22. data/lib/cocoapods/installer/analyzer/target_inspector.rb +6 -8
  23. data/lib/cocoapods/installer/installation_options.rb +4 -0
  24. data/lib/cocoapods/installer/pod_source_installer.rb +17 -1
  25. data/lib/cocoapods/installer/podfile_validator.rb +26 -6
  26. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +37 -27
  27. data/lib/cocoapods/installer/project_cache/project_cache_version.rb +1 -1
  28. data/lib/cocoapods/installer/project_cache/project_installation_cache.rb +3 -3
  29. data/lib/cocoapods/installer/project_cache/project_metadata_cache.rb +12 -6
  30. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +32 -8
  31. data/lib/cocoapods/installer/project_cache/target_metadata.rb +6 -2
  32. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +12 -0
  33. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +1 -1
  34. data/lib/cocoapods/installer/xcode/multi_pods_project_generator.rb +3 -1
  35. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +2 -2
  36. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +18 -3
  37. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +53 -11
  38. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +92 -60
  39. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +66 -50
  40. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +12 -0
  41. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +6 -2
  42. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +2 -2
  43. data/lib/cocoapods/installer/xcode/target_validator.rb +30 -14
  44. data/lib/cocoapods/native_target_extension.rb +11 -5
  45. data/lib/cocoapods/open-uri.rb +1 -1
  46. data/lib/cocoapods/project.rb +13 -7
  47. data/lib/cocoapods/resolver.rb +63 -53
  48. data/lib/cocoapods/resolver/lazy_specification.rb +14 -5
  49. data/lib/cocoapods/sandbox.rb +35 -2
  50. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +3 -4
  51. data/lib/cocoapods/sources_manager.rb +72 -43
  52. data/lib/cocoapods/target.rb +7 -1
  53. data/lib/cocoapods/target/aggregate_target.rb +13 -8
  54. data/lib/cocoapods/target/build_settings.rb +33 -10
  55. data/lib/cocoapods/target/pod_target.rb +114 -30
  56. data/lib/cocoapods/user_interface/error_report.rb +9 -5
  57. data/lib/cocoapods/validator.rb +55 -11
  58. data/lib/cocoapods/version_metadata.rb +14 -1
  59. metadata +6 -7
  60. data/lib/cocoapods/command/spec/env_spec.rb +0 -53
@@ -181,6 +181,10 @@ module Pod
181
181
  # since the previous installation.
182
182
  #
183
183
  option :incremental_installation, false
184
+
185
+ # Whether to skip generating the `Pods.xcodeproj` and perform only dependency resolution and downloading.
186
+ #
187
+ option :skip_pods_project_generation, false
184
188
  end
185
189
  end
186
190
  end
@@ -14,6 +14,11 @@ module Pod
14
14
  #
15
15
  attr_reader :sandbox
16
16
 
17
+ # @return [Podfile] the podfile that should be integrated with the user
18
+ # projects.
19
+ #
20
+ attr_reader :podfile
21
+
17
22
  # @return [Hash{Symbol=>Array}] The specifications that need to be
18
23
  # installed grouped by platform.
19
24
  #
@@ -27,11 +32,13 @@ module Pod
27
32
  # Initialize a new instance
28
33
  #
29
34
  # @param [Sandbox] sandbox @see #sandbox
35
+ # @param [Podfile] podfile @see #podfile
30
36
  # @param [Hash{Symbol=>Array}] specs_by_platform @see #specs_by_platform
31
37
  # @param [Boolean] can_cache @see #can_cache
32
38
  #
33
- def initialize(sandbox, specs_by_platform, can_cache: true)
39
+ def initialize(sandbox, podfile, specs_by_platform, can_cache: true)
34
40
  @sandbox = sandbox
41
+ @podfile = podfile
35
42
  @specs_by_platform = specs_by_platform
36
43
  @can_cache = can_cache
37
44
  end
@@ -61,6 +68,7 @@ module Pod
61
68
  def install!
62
69
  download_source unless predownloaded? || local?
63
70
  PodSourcePreparer.new(root_spec, root).prepare! if local?
71
+ sandbox.remove_local_podspec(name) unless predownloaded? || local? || external?
64
72
  end
65
73
 
66
74
  # Cleans the installations if appropriate.
@@ -191,6 +199,14 @@ module Pod
191
199
  sandbox.local?(root_spec.name)
192
200
  end
193
201
 
202
+ # @return [Boolean] whether the pod uses an external source (e.g. :podspec) in the
203
+ # resolution process to retrieve its podspec.
204
+ #
205
+ def external?
206
+ @dependencies ||= podfile.dependencies.select(&:external?).map(&:name)
207
+ @dependencies.include?(root_spec.name)
208
+ end
209
+
194
210
  def released?
195
211
  !local? && !predownloaded? && sandbox.specification(root_spec.name) != root_spec
196
212
  end
@@ -122,15 +122,35 @@ module Pod
122
122
  end
123
123
 
124
124
  # Verifies that no dependencies in the Podfile will end up not being built
125
- # at all. In other words, all dependencies _must_ belong to a non-abstract
125
+ # at all. In other words, all dependencies should belong to a non-abstract
126
126
  # target, or be inherited by a target where `inheritance == complete`.
127
127
  #
128
128
  def validate_no_abstract_only_pods!
129
- all_dependencies = @podfile_dependency_cache.podfile_dependencies
130
- concrete_dependencies = @podfile_dependency_cache.target_definition_list.reject(&:abstract?).flat_map { |td| @podfile_dependency_cache.target_definition_dependencies(td) }
131
- abstract_only_dependencies = all_dependencies - concrete_dependencies
132
- abstract_only_dependencies.each do |dep|
133
- add_error "The dependency `#{dep}` is not used in any concrete target."
129
+ @podfile_dependency_cache.target_definition_list.each do |target_definition|
130
+ dependencies = @podfile_dependency_cache.target_definition_dependencies(target_definition)
131
+ next if dependencies.empty?
132
+ next unless target_definition.abstract?
133
+
134
+ children = target_definition.recursive_children
135
+ next if children.any? { |child_target_definition| target_definition_inherits?(:parent => target_definition, :child => child_target_definition) }
136
+
137
+ add_warning "The abstract target #{target_definition.name} is not inherited by a concrete target, " \
138
+ "so the following dependencies won't make it into any targets in your project:" \
139
+ "\n - #{dependencies.map(&:to_s).sort.join("\n - ")}"
140
+
141
+ next if target_definition.platform
142
+
143
+ add_error "The abstract target #{target_definition.name} must specify a platform since its dependencies are not inherited by a concrete target."
144
+ end
145
+ end
146
+
147
+ def target_definition_inherits?(parent: nil, child: nil)
148
+ if parent == child
149
+ true
150
+ elsif child.exclusive?
151
+ false
152
+ else
153
+ target_definition_inherits?(:parent => parent, :child => child.parent)
134
154
  end
135
155
  end
136
156
 
@@ -75,15 +75,19 @@ module Pod
75
75
  return full_install_results
76
76
  end
77
77
 
78
+ if project_names_changed?(pod_targets, cache)
79
+ UI.message 'Ignoring project cache due to project name changes.'
80
+ return full_install_results
81
+ end
82
+
78
83
  pod_targets_to_generate = Set[]
79
84
  aggregate_targets_to_generate = Set[]
80
- added_targets, removed_targets = compute_added_and_removed_targets(target_by_label,
81
- cache_key_by_target_label.keys,
82
- cache.cache_key_by_target_label.keys)
85
+ added_targets = compute_added_targets(target_by_label, cache_key_by_target_label.keys, cache.cache_key_by_target_label.keys)
83
86
  added_pod_targets, added_aggregate_targets = added_targets.partition { |target| target.is_a?(PodTarget) }
84
- removed_aggregate_targets = removed_targets.select { |target| target.is_a?(AggregateTarget) }
85
87
  pod_targets_to_generate.merge(added_pod_targets)
86
- aggregate_targets_to_generate.merge(added_aggregate_targets + removed_aggregate_targets)
88
+ aggregate_targets_to_generate.merge(added_aggregate_targets)
89
+
90
+ removed_aggregate_target_labels = compute_removed_targets(cache_key_by_target_label.keys, cache.cache_key_by_target_label.keys)
87
91
 
88
92
  changed_targets = compute_changed_targets_from_cache(cache_key_by_target_label, target_by_label, cache)
89
93
  changed_pod_targets, changed_aggregate_targets = changed_targets.partition { |target| target.is_a?(PodTarget) }
@@ -95,23 +99,21 @@ module Pod
95
99
  pod_targets_to_generate.merge(dirty_pod_targets)
96
100
  aggregate_targets_to_generate.merge(dirty_aggregate_targets)
97
101
 
98
- # Since multi xcodeproj will group targets by PodTarget#pod_name into individual projects, we
99
- # need to append these "sibling" targets to the list of targets we need to generate before finalizing the total list,
102
+ # Since multi xcodeproj will group targets by PodTarget#project_name into individual projects, we need to
103
+ # append these "sibling" targets to the list of targets we need to generate before finalizing the total list,
100
104
  # otherwise we will end up with missing targets.
101
105
  #
102
106
  sibling_pod_targets = compute_sibling_pod_targets(pod_targets, pod_targets_to_generate)
103
107
  pod_targets_to_generate.merge(sibling_pod_targets)
104
108
 
105
- # We either return the full list of aggregate targets or none since the aggregate targets go into the Pods.xcodeproj
106
- # and so we need to regenerate all aggregate targets when regenerating Pods.xcodeproj.
109
+ # We either return the full list of aggregate targets or none since the aggregate targets go into the
110
+ # Pods.xcodeproj and so we need to regenerate all aggregate targets when regenerating Pods.xcodeproj.
111
+ total_aggregate_targets_to_generate = unless aggregate_targets_to_generate.empty? && removed_aggregate_target_labels.empty?
112
+ aggregate_targets
113
+ end
107
114
 
108
- total_aggregate_targets_to_generate =
109
- unless aggregate_targets_to_generate.empty?
110
- aggregate_targets
111
- end
112
-
113
- ProjectCacheAnalysisResult.new(pod_targets_to_generate.to_a, total_aggregate_targets_to_generate, cache_key_by_target_label,
114
- build_configurations, project_object_version)
115
+ ProjectCacheAnalysisResult.new(pod_targets_to_generate.to_a, total_aggregate_targets_to_generate,
116
+ cache_key_by_target_label, build_configurations, project_object_version)
115
117
  end
116
118
 
117
119
  private
@@ -122,23 +124,24 @@ module Pod
122
124
  when PodTarget
123
125
  local = sandbox.local?(target.pod_name)
124
126
  checkout_options = sandbox.checkout_sources[target.pod_name]
125
- [label, TargetCacheKey.from_pod_target(target, :is_local_pod => local, :checkout_options => checkout_options)]
127
+ [label, TargetCacheKey.from_pod_target(sandbox, target, :is_local_pod => local,
128
+ :checkout_options => checkout_options)]
126
129
  when AggregateTarget
127
- [label, TargetCacheKey.from_aggregate_target(target)]
130
+ [label, TargetCacheKey.from_aggregate_target(sandbox, target)]
128
131
  else
129
132
  raise "[BUG] Unknown target type #{target}"
130
133
  end
131
134
  end]
132
135
  end
133
136
 
134
- def compute_added_and_removed_targets(target_by_label, target_labels, cached_target_labels)
135
- added_targets = (target_labels - cached_target_labels).map do |label|
137
+ def compute_added_targets(target_by_label, target_labels, cached_target_labels)
138
+ (target_labels - cached_target_labels).map do |label|
136
139
  target_by_label[label]
137
140
  end
138
- removed_targets = (cached_target_labels - target_labels).map do |label|
139
- target_by_label[label]
140
- end
141
- [added_targets, removed_targets]
141
+ end
142
+
143
+ def compute_removed_targets(target_labels, cached_target_labels)
144
+ cached_target_labels - target_labels
142
145
  end
143
146
 
144
147
  def compute_changed_targets_from_cache(cache_key_by_target_label, target_by_label, cache)
@@ -155,7 +158,7 @@ module Pod
155
158
  support_files_dir_exists = File.exist? target.support_files_dir
156
159
  xcodeproj_exists = case target
157
160
  when PodTarget
158
- File.exist? sandbox.pod_target_project_path(target.pod_name)
161
+ File.exist? sandbox.pod_target_project_path(target.project_name)
159
162
  when AggregateTarget
160
163
  File.exist? sandbox.project_path
161
164
  else
@@ -166,8 +169,15 @@ module Pod
166
169
  end
167
170
 
168
171
  def compute_sibling_pod_targets(pod_targets, pod_targets_to_generate)
169
- pod_targets_by_name = pod_targets.group_by(&:pod_name)
170
- pod_targets_to_generate.flat_map { |t| pod_targets_by_name[t.pod_name] }
172
+ pod_targets_by_project_name = pod_targets.group_by(&:project_name)
173
+ pod_targets_to_generate.flat_map { |t| pod_targets_by_project_name[t.project_name] }
174
+ end
175
+
176
+ def project_names_changed?(pod_targets, cache)
177
+ pod_targets.any? do |pod_target|
178
+ next unless (target_cache_key = cache.cache_key_by_target_label[pod_target.label])
179
+ target_cache_key.project_name != pod_target.project_name
180
+ end
171
181
  end
172
182
  end
173
183
  end
@@ -35,7 +35,7 @@ module Pod
35
35
  # The path of the project cache to save.
36
36
  #
37
37
  def save_as(path)
38
- open(path, 'w') { |f| f.puts version.to_s }
38
+ Sandbox.update_changed_file(path, version.to_s)
39
39
  end
40
40
  end
41
41
  end
@@ -47,15 +47,15 @@ module Pod
47
47
 
48
48
  def save_as(path)
49
49
  Pathname(path).dirname.mkpath
50
- path.open('w') { |f| f.puts YAMLHelper.convert(to_hash) }
50
+ Sandbox.update_changed_file(path, YAMLHelper.convert(to_hash))
51
51
  end
52
52
 
53
- def self.from_file(path)
53
+ def self.from_file(sandbox, path)
54
54
  return ProjectInstallationCache.new unless File.exist?(path)
55
55
  contents = YAMLHelper.load_file(path)
56
56
  cache_keys = contents.fetch('CACHE_KEYS', {})
57
57
  cache_key_by_target_label = Hash[cache_keys.map do |name, key_hash|
58
- [name, TargetCacheKey.from_cache_hash(key_hash)]
58
+ [name, TargetCacheKey.from_cache_hash(sandbox, key_hash)]
59
59
  end]
60
60
  project_object_version = contents['OBJECT_VERSION']
61
61
  build_configurations = contents['BUILD_CONFIGURATIONS']
@@ -6,6 +6,10 @@ module Pod
6
6
  class ProjectMetadataCache
7
7
  require 'cocoapods/installer/project_cache/target_metadata.rb'
8
8
 
9
+ # @return [Sandbox] The sandbox where the Pods should be installed.
10
+ #
11
+ attr_reader :sandbox
12
+
9
13
  # @return [Hash{String => TargetMetadata}]
10
14
  # Hash of string by target metadata.
11
15
  #
@@ -13,9 +17,11 @@ module Pod
13
17
 
14
18
  # Initialize a new instance.
15
19
  #
20
+ # @param [Sandbox] sandbox see #sandbox
16
21
  # @param [Hash{String => TargetMetadata}] target_label_by_metadata @see #target_label_by_metadata
17
22
  #
18
- def initialize(target_label_by_metadata = {})
23
+ def initialize(sandbox, target_label_by_metadata = {})
24
+ @sandbox = sandbox
19
25
  @target_label_by_metadata = target_label_by_metadata
20
26
  end
21
27
 
@@ -32,7 +38,7 @@ module Pod
32
38
  # @return [void]
33
39
  #
34
40
  def save_as(path)
35
- path.open('w') { |f| f.puts YAMLHelper.convert_hash(to_hash, nil) }
41
+ Sandbox.update_changed_file(path, YAMLHelper.convert_hash(to_hash, nil))
36
42
  end
37
43
 
38
44
  # Updates the metadata cache based on installation results.
@@ -47,15 +53,15 @@ module Pod
47
53
  installation_results = pod_target_installation_results.values + aggregate_target_installation_results.values
48
54
  installation_results.each do |installation_result|
49
55
  native_target = installation_result.native_target
50
- target_label_by_metadata[native_target.name] = TargetMetadata.from_native_target(native_target)
56
+ target_label_by_metadata[native_target.name] = TargetMetadata.from_native_target(sandbox, native_target)
51
57
  end
52
58
  end
53
59
 
54
- def self.from_file(path)
55
- return ProjectMetadataCache.new unless File.exist?(path)
60
+ def self.from_file(sandbox, path)
61
+ return ProjectMetadataCache.new(sandbox) unless File.exist?(path)
56
62
  contents = YAMLHelper.load_file(path)
57
63
  target_by_label_metadata = Hash[contents.map { |target_label, hash| [target_label, TargetMetadata.from_hash(hash)] }]
58
- ProjectMetadataCache.new(target_by_label_metadata)
64
+ ProjectMetadataCache.new(sandbox, target_by_label_metadata)
59
65
  end
60
66
  end
61
67
  end
@@ -8,6 +8,10 @@ module Pod
8
8
  require 'cocoapods/target/aggregate_target.rb'
9
9
  require 'digest'
10
10
 
11
+ # @return [Sandbox] The sandbox where the Pods should be installed.
12
+ #
13
+ attr_reader :sandbox
14
+
11
15
  # @return [Symbol]
12
16
  # The type of target. Either aggregate or pod target.
13
17
  #
@@ -20,10 +24,12 @@ module Pod
20
24
 
21
25
  # Initialize a new instance.
22
26
  #
27
+ # @param [Sandbox] sandbox see #sandbox
23
28
  # @param [Symbol] type @see #type
24
29
  # @param [Hash{String => Object}] key_hash @see #key_hash
25
30
  #
26
- def initialize(type, key_hash)
31
+ def initialize(sandbox, type, key_hash)
32
+ @sandbox = sandbox
27
33
  @type = type
28
34
  @key_hash = key_hash
29
35
  end
@@ -46,6 +52,7 @@ module Pod
46
52
  return :project if other.key_hash['CHECKSUM'] != key_hash['CHECKSUM']
47
53
  return :project if other.key_hash['SPECS'] != key_hash['SPECS']
48
54
  return :project if other.key_hash['FILES'] != key_hash['FILES']
55
+ return :project if other.key_hash['PROJECT_NAME'] != key_hash['PROJECT_NAME']
49
56
  end
50
57
 
51
58
  this_build_settings = key_hash['BUILD_SETTINGS_CHECKSUM']
@@ -64,14 +71,23 @@ module Pod
64
71
  key_hash
65
72
  end
66
73
 
74
+ # @return [String]
75
+ # The name of the project the target belongs to.
76
+ #
77
+ def project_name
78
+ key_hash['PROJECT_NAME']
79
+ end
80
+
67
81
  # Creates a TargetCacheKey instance from the given hash.
68
82
  #
83
+ # @param [Sandbox] sandbox The sandbox to use to construct a TargetCacheKey object.
84
+ #
69
85
  # @param [Hash{String => Object}] key_hash
70
86
  # The hash used to construct a TargetCacheKey object.
71
87
  #
72
88
  # @return [TargetCacheKey]
73
89
  #
74
- def self.from_cache_hash(key_hash)
90
+ def self.from_cache_hash(sandbox, key_hash)
75
91
  cache_hash = key_hash.dup
76
92
  if files = cache_hash['FILES']
77
93
  cache_hash['FILES'] = files.sort_by(&:downcase)
@@ -80,11 +96,13 @@ module Pod
80
96
  cache_hash['SPECS'] = specs.sort_by(&:downcase)
81
97
  end
82
98
  type = cache_hash['CHECKSUM'] ? :pod_target : :aggregate
83
- TargetCacheKey.new(type, cache_hash)
99
+ TargetCacheKey.new(sandbox, type, cache_hash)
84
100
  end
85
101
 
86
102
  # Constructs a TargetCacheKey instance from a PodTarget.
87
103
  #
104
+ # @param [Sandbox] sandbox The sandbox to use to construct a TargetCacheKey object.
105
+ #
88
106
  # @param [PodTarget] pod_target
89
107
  # The pod target used to construct a TargetCacheKey object.
90
108
  #
@@ -96,7 +114,7 @@ module Pod
96
114
  #
97
115
  # @return [TargetCacheKey]
98
116
  #
99
- def self.from_pod_target(pod_target, is_local_pod: false, checkout_options: nil)
117
+ def self.from_pod_target(sandbox, pod_target, is_local_pod: false, checkout_options: nil)
100
118
  build_settings = {}
101
119
  build_settings[pod_target.label.to_s] = Digest::MD5.hexdigest(pod_target.build_settings.xcconfig.to_s)
102
120
  pod_target.test_spec_build_settings.each do |name, settings|
@@ -110,26 +128,32 @@ module Pod
110
128
  'CHECKSUM' => pod_target.root_spec.checksum,
111
129
  'SPECS' => pod_target.specs.map(&:to_s).sort_by(&:downcase),
112
130
  'BUILD_SETTINGS_CHECKSUM' => build_settings,
131
+ 'PROJECT_NAME' => pod_target.project_name,
113
132
  }
114
- contents['FILES'] = pod_target.all_files.sort_by(&:downcase) if is_local_pod
133
+ if is_local_pod
134
+ relative_file_paths = pod_target.all_files.map { |f| Pathname.new(f).relative_path_from(sandbox.root).to_s }
135
+ contents['FILES'] = relative_file_paths.sort_by(&:downcase)
136
+ end
115
137
  contents['CHECKOUT_OPTIONS'] = checkout_options if checkout_options
116
- TargetCacheKey.new(:pod_target, contents)
138
+ TargetCacheKey.new(sandbox, :pod_target, contents)
117
139
  end
118
140
 
119
141
  # Construct a TargetCacheKey instance from an AggregateTarget.
120
142
  #
143
+ # @param [Sandbox] sandbox The sandbox to use to construct a TargetCacheKey object.
144
+ #
121
145
  # @param [AggregateTarget] aggregate_target
122
146
  # The aggregate target used to construct a TargetCacheKey object.
123
147
  #
124
148
  # @return [TargetCacheKey]
125
149
  #
126
- def self.from_aggregate_target(aggregate_target)
150
+ def self.from_aggregate_target(sandbox, aggregate_target)
127
151
  build_settings = {}
128
152
  aggregate_target.user_build_configurations.keys.each do |configuration|
129
153
  build_settings[configuration] = Digest::MD5.hexdigest(aggregate_target.build_settings(configuration).xcconfig.to_s)
130
154
  end
131
155
 
132
- TargetCacheKey.new(:aggregate, 'BUILD_SETTINGS_CHECKSUM' => build_settings)
156
+ TargetCacheKey.new(sandbox, :aggregate, 'BUILD_SETTINGS_CHECKSUM' => build_settings)
133
157
  end
134
158
  end
135
159
  end
@@ -56,13 +56,17 @@ module Pod
56
56
 
57
57
  # Constructs a TargetMetadata instance from a native target.
58
58
  #
59
+ # @param [Sandbox] sandbox
60
+ # The sandbox used for this installation.
61
+ #
59
62
  # @param [PBXNativeTarget] native_target
60
63
  # The native target used to construct a TargetMetadata instance.
61
64
  #
62
65
  # @return [TargetMetadata]
63
66
  #
64
- def self.from_native_target(native_target)
65
- TargetMetadata.new(native_target.name, native_target.uuid, native_target.project.path.to_s)
67
+ def self.from_native_target(sandbox, native_target)
68
+ TargetMetadata.new(native_target.name, native_target.uuid,
69
+ native_target.project.path.relative_path_from(sandbox.root).to_s)
66
70
  end
67
71
  end
68
72
  end
@@ -62,6 +62,14 @@ module Pod
62
62
 
63
63
  removed_sandbox_private_headers = sandbox_private_headers(pod_targets) - sandbox_private_headers_to_install
64
64
  removed_sandbox_private_headers.each { |path| remove_dir(path) }
65
+
66
+ project_dir_names_to_install = pod_targets.map do |pod_target|
67
+ sandbox.pod_target_project_path(pod_target.project_name)
68
+ end
69
+ project_dir_names = sandbox_project_dir_names - [sandbox.project_path]
70
+
71
+ removed_project_dir_names = project_dir_names - project_dir_names_to_install
72
+ removed_project_dir_names.each { |dir| remove_dir(dir) }
65
73
  end
66
74
  end
67
75
 
@@ -75,6 +83,10 @@ module Pod
75
83
  pod_targets.flat_map { |pod_target| child_directories_of(pod_target.build_headers.root) }.uniq
76
84
  end
77
85
 
86
+ def sandbox_project_dir_names
87
+ child_directories_of(sandbox.root).select { |d| d.extname == '.xcodeproj' }
88
+ end
89
+
78
90
  def sandbox_public_headers
79
91
  child_directories_of(sandbox.public_headers.root)
80
92
  end