cocoapods-core 0.30.0 → 1.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +7 -10
  3. data/lib/cocoapods-core/build_type.rb +121 -0
  4. data/lib/cocoapods-core/cdn_source.rb +501 -0
  5. data/lib/cocoapods-core/core_ui.rb +4 -3
  6. data/lib/cocoapods-core/dependency.rb +100 -73
  7. data/lib/cocoapods-core/gem_version.rb +1 -2
  8. data/lib/cocoapods-core/github.rb +32 -5
  9. data/lib/cocoapods-core/http.rb +86 -0
  10. data/lib/cocoapods-core/lockfile.rb +161 -56
  11. data/lib/cocoapods-core/metrics.rb +47 -0
  12. data/lib/cocoapods-core/platform.rb +99 -11
  13. data/lib/cocoapods-core/podfile/dsl.rb +623 -124
  14. data/lib/cocoapods-core/podfile/target_definition.rb +662 -109
  15. data/lib/cocoapods-core/podfile.rb +138 -65
  16. data/lib/cocoapods-core/requirement.rb +37 -8
  17. data/lib/cocoapods-core/source/acceptor.rb +16 -13
  18. data/lib/cocoapods-core/source/aggregate.rb +79 -103
  19. data/lib/cocoapods-core/source/health_reporter.rb +9 -18
  20. data/lib/cocoapods-core/source/manager.rb +488 -0
  21. data/lib/cocoapods-core/source/metadata.rb +79 -0
  22. data/lib/cocoapods-core/source.rb +241 -70
  23. data/lib/cocoapods-core/specification/consumer.rb +187 -47
  24. data/lib/cocoapods-core/specification/dsl/attribute.rb +49 -85
  25. data/lib/cocoapods-core/specification/dsl/attribute_support.rb +6 -8
  26. data/lib/cocoapods-core/specification/dsl/deprecations.rb +9 -126
  27. data/lib/cocoapods-core/specification/dsl/platform_proxy.rb +30 -20
  28. data/lib/cocoapods-core/specification/dsl.rb +943 -296
  29. data/lib/cocoapods-core/specification/json.rb +64 -23
  30. data/lib/cocoapods-core/specification/linter/analyzer.rb +218 -0
  31. data/lib/cocoapods-core/specification/linter/result.rb +128 -0
  32. data/lib/cocoapods-core/specification/linter.rb +310 -309
  33. data/lib/cocoapods-core/specification/root_attribute_accessors.rb +90 -39
  34. data/lib/cocoapods-core/specification/set/presenter.rb +35 -71
  35. data/lib/cocoapods-core/specification/set.rb +42 -96
  36. data/lib/cocoapods-core/specification.rb +368 -130
  37. data/lib/cocoapods-core/standard_error.rb +45 -24
  38. data/lib/cocoapods-core/trunk_source.rb +14 -0
  39. data/lib/cocoapods-core/vendor/requirement.rb +133 -53
  40. data/lib/cocoapods-core/vendor/version.rb +197 -156
  41. data/lib/cocoapods-core/vendor.rb +1 -5
  42. data/lib/cocoapods-core/version.rb +137 -42
  43. data/lib/cocoapods-core/yaml_helper.rb +334 -0
  44. data/lib/cocoapods-core.rb +10 -4
  45. metadata +100 -27
  46. data/lib/cocoapods-core/source/abstract_data_provider.rb +0 -71
  47. data/lib/cocoapods-core/source/file_system_data_provider.rb +0 -150
  48. data/lib/cocoapods-core/source/github_data_provider.rb +0 -143
  49. data/lib/cocoapods-core/specification/set/statistics.rb +0 -266
  50. data/lib/cocoapods-core/yaml_converter.rb +0 -192
@@ -1,17 +1,15 @@
1
1
  module Pod
2
2
  class Specification
3
3
  module DSL
4
-
5
4
  # Provides the accessors methods for the root attributes. Root attributes
6
5
  # do not support multi-platform values and inheritance.
7
6
  #
8
7
  module RootAttributesAccessors
9
-
10
8
  # @return [String] The name of the specification *not* including the
11
9
  # names of the parents, in case of ‘sub-specifications’.
12
10
  #
13
11
  def base_name
14
- attributes_hash["name"]
12
+ attributes_hash['name']
15
13
  end
16
14
 
17
15
  # @return [String] The name of the specification including the names of
@@ -21,21 +19,49 @@ module Pod
21
19
  parent ? "#{parent.name}/#{base_name}" : base_name
22
20
  end
23
21
 
24
- # @return [Version] The version of the Pod.
22
+ # @return [Bool, String, Array<String>] The requires_arc value.
25
23
  #
26
- # @todo The version is memoized because the Resolvers sets the head
27
- # state on it. This information should be stored in the
28
- # specification instance and the lockfile should have a more
29
- # robust handling of head versions (like a dedicated section).
24
+ def requires_arc
25
+ attributes_hash['requires_arc']
26
+ end
27
+
28
+ # @return [Version] The version of the Pod.
30
29
  #
31
30
  def version
32
31
  if root?
33
- @version ||= Version.new(attributes_hash["version"])
32
+ @version ||= Version.new(attributes_hash['version'])
34
33
  else
35
34
  @version ||= root.version
36
35
  end
37
36
  end
38
37
 
38
+ # @deprecated in favor of #swift_versions
39
+ #
40
+ # @return [Version] The Swift version specified by the specification.
41
+ #
42
+ def swift_version
43
+ swift_versions.last
44
+ end
45
+
46
+ # @return [Array<Version>] The Swift versions supported by the specification.
47
+ #
48
+ def swift_versions
49
+ @swift_versions ||= begin
50
+ swift_versions = Array(attributes_hash['swift_versions']).dup
51
+ # Pre 1.7.0, the DSL was singularized as it supported only a single version of Swift. In 1.7.0 the DSL
52
+ # is now pluralized always and a specification can support multiple versions of Swift. This ensures
53
+ # we parse the old JSON serialized format and include it as part of the Swift versions supported.
54
+ swift_versions << attributes_hash['swift_version'] unless attributes_hash['swift_version'].nil?
55
+ swift_versions.map { |swift_version| Version.new(swift_version) }.uniq.sort
56
+ end
57
+ end
58
+
59
+ # @return [Requirement] The CocoaPods version required to use the specification.
60
+ #
61
+ def cocoapods_version
62
+ @cocoapods_version ||= Requirement.create(attributes_hash['cocoapods_version'])
63
+ end
64
+
39
65
  # @return [Hash] a hash containing the authors as the keys and their
40
66
  # email address as the values.
41
67
  #
@@ -49,7 +75,7 @@ module Pod
49
75
  # 'Author'
50
76
  #
51
77
  def authors
52
- authors = attributes_hash["authors"]
78
+ authors = attributes_hash['authors']
53
79
  if authors.is_a?(Hash)
54
80
  authors
55
81
  elsif authors.is_a?(Array)
@@ -70,13 +96,19 @@ module Pod
70
96
  # @return [String] The social media URL.
71
97
  #
72
98
  def social_media_url
73
- attributes_hash["social_media_url"]
99
+ attributes_hash['social_media_url']
74
100
  end
75
101
 
76
- # @return [String] The docset URL.
102
+ # @return [String] The readme.
77
103
  #
78
- def docset_url
79
- attributes_hash["docset_url"]
104
+ def readme
105
+ attributes_hash['readme']
106
+ end
107
+
108
+ # @return [String] The changelog.
109
+ #
110
+ def changelog
111
+ attributes_hash['changelog']
80
112
  end
81
113
 
82
114
  # @return [Hash] A hash containing the license information of the Pod.
@@ -84,11 +116,11 @@ module Pod
84
116
  # @note The indentation is stripped from the license text.
85
117
  #
86
118
  def license
87
- license = attributes_hash["license"]
119
+ license = attributes_hash['license']
88
120
  if license.is_a?(String)
89
121
  { :type => license }
90
122
  elsif license.is_a?(Hash)
91
- license = convert_keys_to_symbol(license)
123
+ license = Specification.convert_keys_to_symbol(license)
92
124
  license[:text] = license[:text].strip_heredoc if license[:text]
93
125
  license
94
126
  else
@@ -99,20 +131,26 @@ module Pod
99
131
  # @return [String] The URL of the homepage of the Pod.
100
132
  #
101
133
  def homepage
102
- attributes_hash["homepage"]
134
+ attributes_hash['homepage']
103
135
  end
104
136
 
105
137
  # @return [Hash{Symbol=>String}] The location from where the library
106
138
  # should be retrieved.
107
139
  #
108
140
  def source
109
- convert_keys_to_symbol(attributes_hash["source"])
141
+ value = attributes_hash['source']
142
+ if value && value.is_a?(Hash)
143
+ Specification.convert_keys_to_symbol(value)
144
+ else
145
+ value
146
+ end
110
147
  end
111
148
 
112
149
  # @return [String] A short description of the Pod.
113
150
  #
114
151
  def summary
115
- attributes_hash["summary"]
152
+ summary = attributes_hash['summary']
153
+ summary.strip_heredoc.chomp if summary
116
154
  end
117
155
 
118
156
  # @return [String] A longer description of the Pod.
@@ -120,8 +158,8 @@ module Pod
120
158
  # @note The indentation is stripped from the description.
121
159
  #
122
160
  def description
123
- description = attributes_hash["description"]
124
- description.strip_heredoc if description
161
+ description = attributes_hash['description']
162
+ description.strip_heredoc.chomp if description
125
163
  end
126
164
 
127
165
  # @return [Array<String>] The list of the URL for the screenshots of
@@ -130,45 +168,58 @@ module Pod
130
168
  # @note The value is coerced to an array.
131
169
  #
132
170
  def screenshots
133
- value = attributes_hash["screenshots"]
171
+ value = attributes_hash['screenshots']
134
172
  [*value]
135
173
  end
136
174
 
137
175
  # @return [String, Nil] The documentation URL of the Pod if specified.
138
176
  #
139
177
  def documentation_url
140
- attributes_hash["documentation_url"]
178
+ attributes_hash['documentation_url']
141
179
  end
142
180
 
143
181
  # @return [String, Nil] The prepare command of the Pod if specified.
144
182
  #
145
183
  def prepare_command
146
- attributes_hash["prepare_command"]
184
+ command = attributes_hash['prepare_command']
185
+ command.strip_heredoc.chomp if command
147
186
  end
148
187
 
149
- #---------------------------------------------------------------------#
188
+ # @return [Boolean] Indicates, that if use_frameworks! is specified, the
189
+ # framework should include a static library.
190
+ #
191
+ def static_framework
192
+ attributes_hash['static_framework']
193
+ end
150
194
 
151
- private
195
+ # @return [Boolean] Whether the Pod has been deprecated.
196
+ #
197
+ def deprecated
198
+ attributes_hash['deprecated']
199
+ end
152
200
 
153
- # Converts the keys of the given hash to a string.
201
+ # @return [String] The name of the Pod that this one has been
202
+ # deprecated in favor of.
154
203
  #
155
- # @param [Object] value
156
- # the value that needs to be stripped from the Symbols.
204
+ def deprecated_in_favor_of
205
+ attributes_hash['deprecated_in_favor_of']
206
+ end
207
+
208
+ # @return [Boolean] Wether the pod is deprecated either in favor of some other
209
+ # pod or simply deprecated.
157
210
  #
158
- # @return [Hash] the hash with the strings instead of the keys.
211
+ def deprecated?
212
+ deprecated || !deprecated_in_favor_of.nil?
213
+ end
214
+
215
+ # @return [String, Nil] The custom module map file of the Pod,
216
+ # if specified.
159
217
  #
160
- def convert_keys_to_symbol(value)
161
- return unless value
162
- result = {}
163
- value.each do |key, subvalue|
164
- subvalue = convert_keys_to_symbol(subvalue) if subvalue.is_a?(Hash)
165
- result[key.to_sym] = subvalue
166
- end
167
- result
218
+ def module_map
219
+ attributes_hash['module_map']
168
220
  end
169
221
 
170
222
  #---------------------------------------------------------------------#
171
-
172
223
  end
173
224
  end
174
225
  end
@@ -3,25 +3,18 @@ require 'active_support/core_ext/array/conversions'
3
3
  module Pod
4
4
  class Specification
5
5
  class Set
6
-
7
6
  # Provides support for presenting a Pod described by a {Set} in a
8
7
  # consistent way across clients of CocoaPods-Core.
9
8
  #
10
9
  class Presenter
11
-
12
10
  # @return [Set] the set that should be presented.
13
11
  #
14
12
  attr_reader :set
15
13
 
16
- # @return [Statistics] The statistics provider.
17
- #
18
- attr_reader :statistics_provider
19
-
20
14
  # @param [Set] set @see #set.
21
15
  #
22
- def initialize(set, statistics_provider = nil)
16
+ def initialize(set)
23
17
  @set = set
24
- @statistics_provider = statistics_provider || Statistics.instance
25
18
  end
26
19
 
27
20
  #---------------------------------------------------------------------#
@@ -44,7 +37,7 @@ module Pod
44
37
  # order.
45
38
  #
46
39
  def versions
47
- @set.versions.sort.reverse
40
+ @set.versions
48
41
  end
49
42
 
50
43
  # @return [String] all the versions available sorted from the highest
@@ -56,7 +49,7 @@ module Pod
56
49
  #
57
50
  # @note This method orders the sources by name.
58
51
  #
59
- def verions_by_source
52
+ def versions_by_source
60
53
  result = []
61
54
  versions_by_source = @set.versions_by_source
62
55
  @set.sources.sort.each do |source|
@@ -92,17 +85,9 @@ module Pod
92
85
  #
93
86
  # "Author 1, Author 2 and Author 3"
94
87
  #
95
- # @note In ruby 1.8.7 the authors are sorted by name because the
96
- # hash doesn't preserve the order in which they are defined
97
- # in the podspec.
98
- #
99
88
  def authors
100
89
  return '' unless spec.authors
101
- if RUBY_VERSION == '1.8.7'
102
- spec.authors.keys.sort.to_sentence
103
- else
104
- spec.authors.keys.to_sentence
105
- end
90
+ spec.authors.keys.to_sentence
106
91
  end
107
92
 
108
93
  # @return [String] the homepage of the pod.
@@ -125,6 +110,28 @@ module Pod
125
110
  spec.description || spec.summary
126
111
  end
127
112
 
113
+ # @return [String] A string that describes the deprecation of the pod.
114
+ # If the pod is deprecated in favor of another pod it will contain
115
+ # information about that. If the pod is not deprecated returns nil.
116
+ #
117
+ # @example Output example
118
+ #
119
+ # "[DEPRECATED]"
120
+ # "[DEPRECATED in favor of NewAwesomePod]"
121
+ #
122
+ def deprecation_description
123
+ if spec.deprecated?
124
+ description = '[DEPRECATED'
125
+ description += if spec.deprecated_in_favor_of.nil?
126
+ ']'
127
+ else
128
+ " in favor of #{spec.deprecated_in_favor_of}]"
129
+ end
130
+
131
+ description
132
+ end
133
+ end
134
+
128
135
  # @return [String] the URL of the source of the Pod.
129
136
  #
130
137
  def source_url
@@ -167,72 +174,29 @@ module Pod
167
174
 
168
175
  # @!group Statistics
169
176
 
170
- # @return [Time] the creation date of the first known `podspec` of the
171
- # Pod.
172
- #
173
- def creation_date
174
- statistics_provider.creation_date(@set)
175
- end
176
-
177
177
  # @return [Integer] the GitHub likes of the repo of the Pod.
178
178
  #
179
- def github_watchers
180
- statistics_provider.github_watchers(@set)
179
+ def github_stargazers
180
+ github_metrics['stargazers']
181
181
  end
182
182
 
183
183
  # @return [Integer] the GitHub forks of the repo of the Pod.
184
184
  #
185
185
  def github_forks
186
- statistics_provider.github_forks(@set)
187
- end
188
-
189
- # @return [String] the relative time of the last push of the repo the Pod.
190
- #
191
- def github_last_activity
192
- distance_from_now_in_words(statistics_provider.github_pushed_at(@set))
186
+ github_metrics['forks']
193
187
  end
194
188
 
195
189
  #---------------------------------------------------------------------#
196
190
 
197
- private
198
-
199
- # Computes a human readable string that represents a past date in
200
- # relative terms.
201
- #
202
- # @param [Time, String] from_time
203
- # the date that should be represented.
204
- #
205
- # @example Possible outputs
206
- #
207
- # "less than a week ago"
208
- # "15 days ago"
209
- # "3 month ago"
210
- # "more than a year ago"
211
- #
212
- # @return [String] a string that represents a past date.
213
- #
214
- def distance_from_now_in_words(from_time)
215
- return nil unless from_time
216
- from_time = Time.parse(from_time) unless from_time.is_a?(Time)
217
- to_time = Time.now
218
- distance_in_days = (((to_time - from_time).abs) / 60 / 60 / 24).round
191
+ # @!group Private Helpers
219
192
 
220
- case distance_in_days
221
- when 0..7
222
- "less than a week ago"
223
- when 8..29
224
- "#{distance_in_days} days ago"
225
- when 30..45
226
- "1 month ago"
227
- when 46..365
228
- "#{(distance_in_days.to_f / 30).round} months ago"
229
- else
230
- "more than a year ago"
231
- end
193
+ def metrics
194
+ @metrics ||= Metrics.pod(name) || {}
232
195
  end
233
196
 
234
- #---------------------------------------------------------------------#
235
-
197
+ def github_metrics
198
+ metrics['github'] || {}
199
+ end
236
200
  end
237
201
  end
238
202
  end
@@ -1,22 +1,19 @@
1
1
  require 'active_support/core_ext/array/conversions'
2
2
  require 'cocoapods-core/specification/set/presenter'
3
- require 'cocoapods-core/specification/set/statistics'
4
3
 
5
4
  module Pod
6
5
  class Specification
7
-
8
6
  # A Specification::Set is responsible of handling all the specifications of
9
7
  # a Pod. This class stores the information of the dependencies that required
10
8
  # a Pod in the resolution process.
11
9
  #
12
- # @note The alphabetical order of the sets is used to select a
10
+ # @note The order in which the sets are provided is used to select a
13
11
  # specification if multiple are available for a given version.
14
12
  #
15
13
  # @note The set class is not and should be not aware of the backing store
16
14
  # of a Source.
17
15
  #
18
16
  class Set
19
-
20
17
  # @return [String] the name of the Pod.
21
18
  #
22
19
  attr_reader :name
@@ -33,104 +30,49 @@ module Pod
33
30
  # the sources that contain a Pod.
34
31
  #
35
32
  def initialize(name, sources = [])
36
- @name = name
37
- sources = sources.is_a?(Array) ? sources : [sources]
38
- @sources = sources.sort_by(&:name)
39
- @dependencies_by_requirer_name = {}
40
- @dependencies = []
41
- end
42
-
43
- # Stores a dependency on the Pod.
44
- #
45
- # @param [Dependency] dependency
46
- # a dependency that requires the Pod.
47
- #
48
- # @param [String] dependent_name
49
- # the name of the owner of the dependency. It is used only to
50
- # display the Pod::Informative.
51
- #
52
- # @raise If the versions requirement of the dependency are not
53
- # compatible with the previously stored dependencies.
54
- #
55
- # @todo This should simply return a boolean. Is CocoaPods that should
56
- # raise.
57
- #
58
- # @return [void]
59
- #
60
- def required_by(dependency, dependent_name)
61
- dependencies_by_requirer_name[dependent_name] ||= []
62
- dependencies_by_requirer_name[dependent_name] << dependency
63
- dependencies << dependency
64
-
65
- if acceptable_versions.empty?
66
- message = "Unable to satisfy the following requirements:\n"
67
- dependencies_by_requirer_name.each do |name, dependencies|
68
- dependencies.each do |dep|
69
- message << "- `#{dep}` required by `#{name}`"
70
- end
71
- end
72
- raise Informative, message
73
- end
74
- end
75
-
76
- # @return [Dependency] A dependency that includes all the versions
77
- # requirements of the stored dependencies.
78
- #
79
- def dependency
80
- dependencies.reduce(Dependency.new(name)) do |previous, dependency|
81
- previous.merge(dependency.to_root_dependency)
82
- end
33
+ @name = name
34
+ @sources = Array(sources)
83
35
  end
84
36
 
85
37
  # @return [Specification] the top level specification of the Pod for the
86
38
  # {#required_version}.
87
39
  #
88
40
  # @note If multiple sources have a specification for the
89
- # {#required_version} The alphabetical order of their names is
90
- # used to disambiguate.
41
+ # {#required_version}, the order in which they are provided
42
+ # is used to disambiguate.
91
43
  #
92
44
  def specification
93
- path = specification_path_for_version(required_version)
94
- Specification.from_file(path)
95
- end
96
-
97
- # TODO
98
- #
99
- def specification_path_for_version(version)
100
- sources = []
101
- versions_by_source.each do |source, source_versions|
102
- sources << source if source_versions.include?(required_version)
45
+ unless highest_version_spec_path
46
+ raise Informative, "Could not find the highest version for `#{name}`. "\
47
+ "This could be due to an empty #{name} directory in a local repository."
103
48
  end
104
- source = sources.sort_by(&:name).first
105
- source.specification_path(name, required_version)
49
+
50
+ Specification.from_file(highest_version_spec_path)
106
51
  end
107
52
 
108
- # @return [Version] the highest version that satisfies the stored
109
- # dependencies.
110
- #
111
- # @todo This should simply return nil. CocoaPods should raise instead.
53
+ # @return [Specification] the top level specification for this set for any version.
112
54
  #
113
- def required_version
114
- version = versions.find { |v| dependency.match?(name, v) }
115
- unless version
116
- raise Informative, "Required version (#{dependency}) not found " \
117
- "for `#{name}`.\nAvailable versions: #{versions.join(', ')}"
55
+ def specification_name
56
+ versions_by_source.each do |source, versions|
57
+ next unless version = versions.first
58
+ return source.specification(name, version).name
118
59
  end
119
- version
60
+ nil
120
61
  end
121
62
 
122
- # @return [Array<Version>] All the versions which are acceptable given
123
- # the requirements.
63
+ # @return [Array<String>] the paths to specifications for the given
64
+ # version
124
65
  #
125
- def acceptable_versions
126
- versions.select { |v| dependency.match?(name, v) }
66
+ def specification_paths_for_version(version)
67
+ sources = @sources.select { |source| versions_by_source[source].include?(version) }
68
+ sources.map { |source| source.specification_path(name, version) }
127
69
  end
128
70
 
129
71
  # @return [Array<Version>] all the available versions for the Pod, sorted
130
72
  # from highest to lowest.
131
73
  #
132
74
  def versions
133
- versions_by_source.values.flatten.uniq.sort.reverse
75
+ @versions ||= versions_by_source.values.flatten.uniq.sort.reverse
134
76
  end
135
77
 
136
78
  # @return [Version] The highest version known of the specification.
@@ -141,19 +83,21 @@ module Pod
141
83
 
142
84
  # @return [Pathname] The path of the highest version.
143
85
  #
86
+ # @note If multiple sources have a specification for the
87
+ # {#required_version}, the order in which they are provided
88
+ # is used to disambiguate.
89
+ #
144
90
  def highest_version_spec_path
145
- specification_path_for_version(highest_version)
91
+ @highest_version_spec_path ||= specification_paths_for_version(highest_version).first
146
92
  end
147
93
 
148
94
  # @return [Hash{Source => Version}] all the available versions for the
149
95
  # Pod grouped by source.
150
96
  #
151
97
  def versions_by_source
152
- result = {}
153
- sources.each do |source|
98
+ @versions_by_source ||= sources.each_with_object({}) do |source, result|
154
99
  result[source] = source.versions(name)
155
100
  end
156
- result
157
101
  end
158
102
 
159
103
  def ==(other)
@@ -163,8 +107,7 @@ module Pod
163
107
  end
164
108
 
165
109
  def to_s
166
- "#<#{self.class.name} for `#{name}' with required version " \
167
- "`#{required_version}' available at `#{sources.map(&:name) * ', '}'>"
110
+ "#<#{self.class.name} for `#{name}' available at `#{sources.map(&:name).join(', ')}'>"
168
111
  end
169
112
  alias_method :inspect, :to_s
170
113
 
@@ -194,11 +137,6 @@ module Pod
194
137
 
195
138
  #-----------------------------------------------------------------------#
196
139
 
197
- attr_accessor :dependencies_by_requirer_name
198
- attr_accessor :dependencies
199
-
200
- #-----------------------------------------------------------------------#
201
-
202
140
  # The Set::External class handles Pods from external sources. Pods from
203
141
  # external sources don't use the {Source} and are initialized by a given
204
142
  # specification.
@@ -206,7 +144,6 @@ module Pod
206
144
  # @note External sources *don't* support subspecs.
207
145
  #
208
146
  class External < Set
209
-
210
147
  attr_reader :specification
211
148
 
212
149
  def initialize(spec)
@@ -218,14 +155,23 @@ module Pod
218
155
  self.class == other.class && specification == other.specification
219
156
  end
220
157
 
221
- def specification_path
222
- raise StandardError, "specification_path"
223
- end
224
-
225
158
  def versions
226
159
  [specification.version]
227
160
  end
228
161
  end
162
+
163
+ #-----------------------------------------------------------------------#
164
+
165
+ # The Set::Head class handles Pods in head mode. Pods in head
166
+ # mode don't use the {Source} and are initialized by a given
167
+ # specification.
168
+ #
169
+ class Head < External
170
+ def initialize(spec)
171
+ super
172
+ specification.version.head = true
173
+ end
174
+ end
229
175
  end
230
176
  end
231
177
  end