cocoapods-core 0.17.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +36 -0
- data/lib/cocoapods-core/core_ui.rb +19 -0
- data/lib/cocoapods-core/dependency.rb +295 -0
- data/lib/cocoapods-core/gem_version.rb +6 -0
- data/lib/cocoapods-core/lockfile.rb +440 -0
- data/lib/cocoapods-core/platform.rb +171 -0
- data/lib/cocoapods-core/podfile/dsl.rb +459 -0
- data/lib/cocoapods-core/podfile/target_definition.rb +503 -0
- data/lib/cocoapods-core/podfile.rb +345 -0
- data/lib/cocoapods-core/requirement.rb +15 -0
- data/lib/cocoapods-core/source/validator.rb +183 -0
- data/lib/cocoapods-core/source.rb +284 -0
- data/lib/cocoapods-core/specification/consumer.rb +356 -0
- data/lib/cocoapods-core/specification/dsl/attribute.rb +245 -0
- data/lib/cocoapods-core/specification/dsl/attribute_support.rb +76 -0
- data/lib/cocoapods-core/specification/dsl/deprecations.rb +47 -0
- data/lib/cocoapods-core/specification/dsl/platform_proxy.rb +67 -0
- data/lib/cocoapods-core/specification/dsl.rb +1110 -0
- data/lib/cocoapods-core/specification/linter.rb +436 -0
- data/lib/cocoapods-core/specification/root_attribute_accessors.rb +152 -0
- data/lib/cocoapods-core/specification/set/presenter.rb +229 -0
- data/lib/cocoapods-core/specification/set/statistics.rb +277 -0
- data/lib/cocoapods-core/specification/set.rb +171 -0
- data/lib/cocoapods-core/specification/yaml.rb +60 -0
- data/lib/cocoapods-core/specification.rb +592 -0
- data/lib/cocoapods-core/standard_error.rb +84 -0
- data/lib/cocoapods-core/vendor/dependency.rb +264 -0
- data/lib/cocoapods-core/vendor/requirement.rb +208 -0
- data/lib/cocoapods-core/vendor/version.rb +333 -0
- data/lib/cocoapods-core/vendor.rb +56 -0
- data/lib/cocoapods-core/version.rb +99 -0
- data/lib/cocoapods-core/yaml_converter.rb +202 -0
- data/lib/cocoapods-core.rb +23 -0
- metadata +154 -0
@@ -0,0 +1,345 @@
|
|
1
|
+
require 'cocoapods-core/podfile/dsl'
|
2
|
+
require 'cocoapods-core/podfile/target_definition'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
|
6
|
+
# The Podfile is a specification that describes the dependencies of the
|
7
|
+
# targets of an Xcode project.
|
8
|
+
#
|
9
|
+
# It supports its own DSL and generally is stored in files named
|
10
|
+
# `CocoaPods.podfile` or `Podfile`.
|
11
|
+
#
|
12
|
+
# The Podfile creates a hierarchy of target definitions that that store the
|
13
|
+
# information of necessary to generate the CocoaPods libraries.
|
14
|
+
#
|
15
|
+
class Podfile
|
16
|
+
|
17
|
+
# @!group DSL support
|
18
|
+
|
19
|
+
include Pod::Podfile::DSL
|
20
|
+
|
21
|
+
#-------------------------------------------------------------------------#
|
22
|
+
|
23
|
+
class Pod::Podfile::StandardError < StandardError; end
|
24
|
+
|
25
|
+
#-------------------------------------------------------------------------#
|
26
|
+
|
27
|
+
# @return [Pathname] the path where the podfile was loaded from. It is nil
|
28
|
+
# if the podfile was generated programmatically.
|
29
|
+
#
|
30
|
+
attr_accessor :defined_in_file
|
31
|
+
|
32
|
+
# @param [Pathname] defined_in_file
|
33
|
+
# the path of the podfile.
|
34
|
+
#
|
35
|
+
# @param [Proc] block
|
36
|
+
# an optional block that configures the podfile through the DSL.
|
37
|
+
#
|
38
|
+
# @example Creating a Podfile.
|
39
|
+
#
|
40
|
+
# platform :ios, "6.0"
|
41
|
+
# target :my_app do
|
42
|
+
# pod "AFNetworking", "~> 1.0"
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
def initialize(defined_in_file = nil, internal_hash = {}, &block)
|
46
|
+
self.defined_in_file = defined_in_file
|
47
|
+
@internal_hash = internal_hash
|
48
|
+
if block
|
49
|
+
default_target_def = TargetDefinition.new(:default, self)
|
50
|
+
@root_target_definitions = [default_target_def]
|
51
|
+
@current_target_definition = default_target_def
|
52
|
+
instance_eval(&block)
|
53
|
+
else
|
54
|
+
@root_target_definitions = []
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [String] a string useful to represent the Podfile in a message
|
59
|
+
# presented to the user.
|
60
|
+
#
|
61
|
+
def to_s
|
62
|
+
"Podfile"
|
63
|
+
end
|
64
|
+
|
65
|
+
#-------------------------------------------------------------------------#
|
66
|
+
|
67
|
+
public
|
68
|
+
|
69
|
+
# @!group Working with a podfile
|
70
|
+
|
71
|
+
# @return [Hash{Symbol,String => TargetDefinition}] the target definitions
|
72
|
+
# of the podfile stored by their name.
|
73
|
+
#
|
74
|
+
def target_definitions
|
75
|
+
Hash[target_definition_list.map { |td| [td.name, td] }]
|
76
|
+
end
|
77
|
+
|
78
|
+
def target_definition_list
|
79
|
+
root_target_definitions.map { |td| [td, td.recursive_children] }.flatten
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [Array<TargetDefinition>] The root target definition.
|
83
|
+
#
|
84
|
+
attr_accessor :root_target_definitions
|
85
|
+
|
86
|
+
# @return [Array<Dependency>] the dependencies of the all the target
|
87
|
+
# definitions.
|
88
|
+
#
|
89
|
+
def dependencies
|
90
|
+
target_definition_list.map(&:dependencies).flatten.uniq
|
91
|
+
end
|
92
|
+
|
93
|
+
#-------------------------------------------------------------------------#
|
94
|
+
|
95
|
+
public
|
96
|
+
|
97
|
+
# @!group Attributes
|
98
|
+
|
99
|
+
# @return [String] the path of the workspace if specified by the user.
|
100
|
+
#
|
101
|
+
def workspace_path
|
102
|
+
path = get_hash_value('workspace')
|
103
|
+
if path
|
104
|
+
if File.extname(path) == '.xcworkspace'
|
105
|
+
path
|
106
|
+
else
|
107
|
+
"#{path}.xcworkspace"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# @return [Bool] whether the podfile should generate a BridgeSupport
|
113
|
+
# metadata document.
|
114
|
+
#
|
115
|
+
def generate_bridge_support?
|
116
|
+
get_hash_value('generate_bridge_support')
|
117
|
+
end
|
118
|
+
|
119
|
+
# @return [Bool] whether the -fobjc-arc flag should be added to the
|
120
|
+
# OTHER_LD_FLAGS.
|
121
|
+
#
|
122
|
+
def set_arc_compatibility_flag?
|
123
|
+
get_hash_value('set_arc_compatibility_flag')
|
124
|
+
end
|
125
|
+
|
126
|
+
#-------------------------------------------------------------------------#
|
127
|
+
|
128
|
+
public
|
129
|
+
|
130
|
+
# @!group Hooks
|
131
|
+
|
132
|
+
# Calls the pre install callback if defined.
|
133
|
+
#
|
134
|
+
# @param [Pod::Installer] installer
|
135
|
+
# the installer that is performing the installation.
|
136
|
+
#
|
137
|
+
# @return [Bool] whether a pre install callback was specified and it was
|
138
|
+
# called.
|
139
|
+
#
|
140
|
+
def pre_install!(installer)
|
141
|
+
if @pre_install_callback
|
142
|
+
@pre_install_callback.call(installer)
|
143
|
+
true
|
144
|
+
else
|
145
|
+
false
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Calls the post install callback if defined.
|
150
|
+
#
|
151
|
+
# @param [Pod::Installer] installer
|
152
|
+
# the installer that is performing the installation.
|
153
|
+
#
|
154
|
+
# @return [Bool] whether a post install callback was specified and it was
|
155
|
+
# called.
|
156
|
+
#
|
157
|
+
def post_install!(installer)
|
158
|
+
if @post_install_callback
|
159
|
+
@post_install_callback.call(installer)
|
160
|
+
true
|
161
|
+
else
|
162
|
+
false
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
#-------------------------------------------------------------------------#
|
167
|
+
|
168
|
+
public
|
169
|
+
|
170
|
+
# @!group Representations
|
171
|
+
|
172
|
+
# @return [Array] The keys used by the hash representation of the Podfile.
|
173
|
+
#
|
174
|
+
HASH_KEYS = [
|
175
|
+
'target_definitions',
|
176
|
+
'workspace',
|
177
|
+
'generate_bridge_support',
|
178
|
+
'set_arc_compatibility_flag',
|
179
|
+
].freeze
|
180
|
+
|
181
|
+
# @return [Hash] The hash representation of the Podfile.
|
182
|
+
#
|
183
|
+
def to_hash
|
184
|
+
hash = {}
|
185
|
+
hash['target_definitions'] = Hash[root_target_definitions.map { |child| [child.name, child.to_hash] }]
|
186
|
+
hash.merge!(internal_hash)
|
187
|
+
hash
|
188
|
+
end
|
189
|
+
|
190
|
+
# @return [String] The YAML representation of the Podfile.
|
191
|
+
#
|
192
|
+
def to_yaml
|
193
|
+
to_hash.to_yaml
|
194
|
+
end
|
195
|
+
|
196
|
+
#-------------------------------------------------------------------------#
|
197
|
+
|
198
|
+
public
|
199
|
+
|
200
|
+
# @!group Class methods
|
201
|
+
|
202
|
+
# Initializes a podfile from the file with the given path.
|
203
|
+
#
|
204
|
+
# @param [Pathname] path
|
205
|
+
# the path from where the podfile should be loaded.
|
206
|
+
#
|
207
|
+
# @return [Podfile] the generated podfile.
|
208
|
+
#
|
209
|
+
def self.from_file(path)
|
210
|
+
path = Pathname.new(path)
|
211
|
+
unless path.exist?
|
212
|
+
raise StandardError, "No Podfile exists at path `#{path}`."
|
213
|
+
end
|
214
|
+
string = File.open(path, 'r:utf-8') { |f| f.read }
|
215
|
+
# Work around for Rubinius incomplete encoding in 1.9 mode
|
216
|
+
if string.respond_to?(:encoding) && string.encoding.name != "UTF-8"
|
217
|
+
string.encode!('UTF-8')
|
218
|
+
end
|
219
|
+
|
220
|
+
case path.extname
|
221
|
+
when ''
|
222
|
+
Podfile.from_ruby(string, path)
|
223
|
+
when '.yaml', '.cocoapods'
|
224
|
+
Podfile.from_yaml(string, path)
|
225
|
+
else
|
226
|
+
raise StandardError, "Unsupported Podfile format `#{path}`."
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# Configures a new Podfile from the given ruby string.
|
231
|
+
#
|
232
|
+
# @param [String] string
|
233
|
+
# The ruby string which will configure the podfile with the DSL.
|
234
|
+
#
|
235
|
+
# @param [Pathname] path
|
236
|
+
# The path from which the Podfile is loaded.
|
237
|
+
#
|
238
|
+
# @return [Podfile] the new Podfile
|
239
|
+
#
|
240
|
+
def self.from_ruby(string, path = nil)
|
241
|
+
podfile = Podfile.new(path) do
|
242
|
+
begin
|
243
|
+
eval(string, nil, path.to_s)
|
244
|
+
rescue Exception => e
|
245
|
+
raise DSLError.new("Invalid `#{path.basename}` file: #{e.message}", path, e.backtrace)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
podfile
|
249
|
+
end
|
250
|
+
|
251
|
+
# Configures a new Podfile from the given hash.
|
252
|
+
#
|
253
|
+
# @param [Hash] hash
|
254
|
+
# The hash which contains the information of the Podfile.
|
255
|
+
#
|
256
|
+
# @param [Pathname] path
|
257
|
+
# The path from which the Podfile is loaded.
|
258
|
+
#
|
259
|
+
# @return [Podfile] the new Podfile
|
260
|
+
#
|
261
|
+
def self.from_hash(hash, path = nil)
|
262
|
+
internal_hash = hash.dup
|
263
|
+
target_definitions = internal_hash.delete('target_definitions') || []
|
264
|
+
podfile = Podfile.new(path,internal_hash)
|
265
|
+
target_definitions.each do |name, definition_hash|
|
266
|
+
definition = TargetDefinition.from_hash(name, definition_hash, podfile)
|
267
|
+
podfile.root_target_definitions << definition
|
268
|
+
end
|
269
|
+
podfile
|
270
|
+
end
|
271
|
+
|
272
|
+
# Configures a new Podfile from the given YAML representation.
|
273
|
+
#
|
274
|
+
# @param [String] yaml
|
275
|
+
# The YAML encoded hash which contains the information of the
|
276
|
+
# Podfile.
|
277
|
+
#
|
278
|
+
# @param [Pathname] path
|
279
|
+
# The path from which the Podfile is loaded.
|
280
|
+
#
|
281
|
+
# @return [Podfile] the new Podfile
|
282
|
+
#
|
283
|
+
def self.from_yaml(yaml, path = nil)
|
284
|
+
hash = YAML.load(yaml)
|
285
|
+
from_hash(hash)
|
286
|
+
end
|
287
|
+
|
288
|
+
#-------------------------------------------------------------------------#
|
289
|
+
|
290
|
+
private
|
291
|
+
|
292
|
+
# @!group Private helpers
|
293
|
+
|
294
|
+
# @return [Hash] The hash which store the attributes of the Podfile.
|
295
|
+
#
|
296
|
+
attr_accessor :internal_hash
|
297
|
+
|
298
|
+
# Set a value in the internal hash of the Podfile for the given key.
|
299
|
+
#
|
300
|
+
# @param [String] key
|
301
|
+
# The key for which to store the value.
|
302
|
+
#
|
303
|
+
# @param [Object] value
|
304
|
+
# The value to store.
|
305
|
+
#
|
306
|
+
# @raise If the key is not recognized.
|
307
|
+
#
|
308
|
+
# @return [void]
|
309
|
+
#
|
310
|
+
def set_hash_value(key, value)
|
311
|
+
raise StandardError, "Unsupported hash key `#{key}`" unless HASH_KEYS.include?(key)
|
312
|
+
internal_hash[key] = value
|
313
|
+
end
|
314
|
+
|
315
|
+
# Returns the value for the given key in the internal hash of the Podfile.
|
316
|
+
#
|
317
|
+
# @param [String] key
|
318
|
+
# The key for which the value is needed.
|
319
|
+
#
|
320
|
+
# @raise If the key is not recognized.
|
321
|
+
#
|
322
|
+
# @return [Object] The value for the key.
|
323
|
+
#
|
324
|
+
def get_hash_value(key)
|
325
|
+
raise StandardError, "Unsupported hash key `#{key}`" unless HASH_KEYS.include?(key)
|
326
|
+
internal_hash[key]
|
327
|
+
end
|
328
|
+
|
329
|
+
# @return [TargetDefinition] The current target definition to which the DSL
|
330
|
+
# commands apply.
|
331
|
+
#
|
332
|
+
attr_accessor :current_target_definition
|
333
|
+
|
334
|
+
#-------------------------------------------------------------------------#
|
335
|
+
|
336
|
+
# @deprecated Deprecated in favour of the more succinct {#pod}. Remove for
|
337
|
+
# CocoaPods 1.0.
|
338
|
+
#
|
339
|
+
def dependency(name = nil, *requirements, &block)
|
340
|
+
warn "[DEPRECATED] `dependency' is deprecated (use `pod')"
|
341
|
+
pod(name, *requirements, &block)
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Pod
|
2
|
+
|
3
|
+
# A Requirement is a set of one or more version restrictions of a
|
4
|
+
# {Dependency}.
|
5
|
+
#
|
6
|
+
# It is based on the RubyGems class adapted to support CocoaPods specific
|
7
|
+
# information.
|
8
|
+
#
|
9
|
+
# @todo Move support about external sources and head information here from
|
10
|
+
# the Dependency class.
|
11
|
+
#
|
12
|
+
class Requirement < Pod::Vendor::Gem::Requirement
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
module Pod
|
2
|
+
class Source
|
3
|
+
|
4
|
+
# TODO: THIS CLASS IS A STUB
|
5
|
+
|
6
|
+
# Checks whether a podspec can be accepted by a source.
|
7
|
+
#
|
8
|
+
# This class can work on Travis but some checks are lost as the repo is
|
9
|
+
# already merged during the test.
|
10
|
+
#
|
11
|
+
class Validator
|
12
|
+
|
13
|
+
# @return [Source] the source where the podspec should be added.
|
14
|
+
#
|
15
|
+
attr_reader :source
|
16
|
+
|
17
|
+
# @param [Pathname] repo @see Source#repo.
|
18
|
+
#
|
19
|
+
def initialize(repo)
|
20
|
+
@source = Source.new(repo)
|
21
|
+
@errors = {}
|
22
|
+
@linter_results = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [Array<Pathname>] spec_paths
|
26
|
+
# a list of path that should be checked for being accepted in
|
27
|
+
# specs repo.
|
28
|
+
#
|
29
|
+
# @return [Bool] whether to podspec can be accepted by the source.
|
30
|
+
#
|
31
|
+
def check(spec_paths)
|
32
|
+
spec_paths = [ spec_paths ] unless spec_paths.is_a?(Array)
|
33
|
+
@errors = {}
|
34
|
+
spec_paths.each do |path|
|
35
|
+
@spec_path = Pathname.new(path)
|
36
|
+
lint
|
37
|
+
next unless spec
|
38
|
+
# check_spec_path
|
39
|
+
check_spec_source_change
|
40
|
+
check_if_untagged_version_is_acceptable
|
41
|
+
check_commit_change_for_untagged_version
|
42
|
+
check_dependencies
|
43
|
+
end
|
44
|
+
errors.values.empty?
|
45
|
+
end
|
46
|
+
|
47
|
+
#-----------------------------------------------------------------------#
|
48
|
+
|
49
|
+
# @!group Validation results
|
50
|
+
|
51
|
+
public
|
52
|
+
|
53
|
+
|
54
|
+
# @return [Hash{Pathname=>Array<String>}] the errors generated by the
|
55
|
+
# validation. If there is any error the podspec cannot be
|
56
|
+
# accepted.
|
57
|
+
#
|
58
|
+
attr_reader :errors
|
59
|
+
|
60
|
+
# @return [Hash{Pathname=>Array<Specification::Linter::Result>}] the
|
61
|
+
# result generated by the linter for not approved specifications.
|
62
|
+
#
|
63
|
+
attr_reader :linter_results
|
64
|
+
|
65
|
+
#-----------------------------------------------------------------------#
|
66
|
+
|
67
|
+
# @!group Validation helpers
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# @return [Pathname] The path of the current specification that should be
|
72
|
+
# checked.
|
73
|
+
#
|
74
|
+
attr_reader :spec_path
|
75
|
+
|
76
|
+
# @return [Specification] The current specification that should be
|
77
|
+
# checked.
|
78
|
+
#
|
79
|
+
# @note The specification is generated by the linter that catches any
|
80
|
+
# exception.
|
81
|
+
#
|
82
|
+
attr_reader :spec
|
83
|
+
|
84
|
+
|
85
|
+
#
|
86
|
+
#
|
87
|
+
def error(message)
|
88
|
+
@errors[spec_path] ||= []
|
89
|
+
@errors[spec_path] << message
|
90
|
+
end
|
91
|
+
|
92
|
+
#-----------------------------------------------------------------------#
|
93
|
+
|
94
|
+
# @!group Check steps
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def lint
|
99
|
+
linter = Specification::Linter.new(spec_path)
|
100
|
+
if linter.lint
|
101
|
+
@spec = linter.spec
|
102
|
+
else
|
103
|
+
error 'Linter failed validation.'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# TODO: this check cannot be performed before a merge.
|
108
|
+
def check_spec_path
|
109
|
+
expected = "#{spec.name}/#{spec.version}/#{spec.name}.podspec"
|
110
|
+
relative_path = spec_path.relative_path_from(source.repo).to_s
|
111
|
+
unless relative_path == expected
|
112
|
+
error "Incorrect path, the path is `#{relative_path}` and should be `#{expected}`."
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def check_spec_source_change
|
117
|
+
return unless spec
|
118
|
+
return unless reference_spec
|
119
|
+
keys = Spec::DSL::SOURCE_KEYS.keys
|
120
|
+
source = spec.source.values_at(*keys).compact.first
|
121
|
+
old_source = reference_spec.source.values_at(*keys).compact.first
|
122
|
+
unless source == old_source
|
123
|
+
error "Attempt to change the source of the specification. " \
|
124
|
+
"Source: `#{source}`. Previous: `#{old_source}`.\n " \
|
125
|
+
"Contact specs repos maintainers if the library changed location."
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def check_if_untagged_version_is_acceptable
|
130
|
+
return unless spec
|
131
|
+
return if !spec.source[:git] || spec.source[:tag]
|
132
|
+
|
133
|
+
# Allow to fix a 0.0.1 podspec
|
134
|
+
if !related_specifications.any? { |s| s.version == '0.0.1' }
|
135
|
+
error "There is already versioned specifications so " \
|
136
|
+
"untagged versions cannot be added."
|
137
|
+
elsif spec.version != Version.new('0.0.1')
|
138
|
+
error "Untagged Git repositories should be versioned as 0.0.1"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# TODO: this cannot be tested on Travis with the current setup
|
143
|
+
def check_commit_change_for_untagged_version
|
144
|
+
return unless spec
|
145
|
+
return unless spec.version == Version.new('0.0.1')
|
146
|
+
ref_spec = related_specifications.find { |s| s.version != '0.0.1' }
|
147
|
+
return unless ref_spec
|
148
|
+
unless ref_spec.source[:commit] == spec.source[:commit]
|
149
|
+
error "Attempt to rewrite the commit of 0.0.1 version."
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def check_dependencies
|
154
|
+
return unless spec
|
155
|
+
spec.external_dependencies(true).each do |dep|
|
156
|
+
set = source.search(dep)
|
157
|
+
unless set && set.specification
|
158
|
+
error "Unable to find a specification for the `#{dep}` dependency."
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
#-----------------------------------------------------------------------#
|
164
|
+
|
165
|
+
# @!group Source helpers
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
def related_specifications
|
170
|
+
versions = source.versions(spec.name)
|
171
|
+
return unless versions
|
172
|
+
specs = versions.sort.map { |v| source.specification(spec.name, v) }
|
173
|
+
specs.reject { |s| s.defined_in_file == spec_path }
|
174
|
+
end
|
175
|
+
|
176
|
+
def reference_spec
|
177
|
+
specs = related_specifications
|
178
|
+
specs.last if specs
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|