cocoapods-core 0.17.0.rc5 → 0.17.0.rc6
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 +4 -4
- data/README.md +16 -8
- data/lib/cocoapods-core.rb +1 -0
- data/lib/cocoapods-core/core_ui.rb +8 -8
- data/lib/cocoapods-core/dependency.rb +7 -4
- data/lib/cocoapods-core/gem_version.rb +1 -1
- data/lib/cocoapods-core/lockfile.rb +12 -22
- data/lib/cocoapods-core/platform.rb +1 -1
- data/lib/cocoapods-core/podfile.rb +8 -3
- data/lib/cocoapods-core/podfile/dsl.rb +1 -3
- data/lib/cocoapods-core/podfile/target_definition.rb +1 -5
- data/lib/cocoapods-core/source.rb +8 -112
- data/lib/cocoapods-core/source/acceptor.rb +159 -0
- data/lib/cocoapods-core/source/aggregate.rb +229 -0
- data/lib/cocoapods-core/source/health_reporter.rb +208 -0
- data/lib/cocoapods-core/specification.rb +11 -5
- data/lib/cocoapods-core/specification/consumer.rb +1 -7
- data/lib/cocoapods-core/specification/dsl.rb +4 -3
- data/lib/cocoapods-core/specification/dsl/deprecations.rb +9 -4
- data/lib/cocoapods-core/specification/linter.rb +52 -29
- data/lib/cocoapods-core/specification/set/presenter.rb +2 -2
- data/lib/cocoapods-core/version.rb +3 -0
- data/lib/cocoapods-core/yaml_converter.rb +2 -13
- metadata +5 -3
- data/lib/cocoapods-core/source/validator.rb +0 -183
@@ -0,0 +1,159 @@
|
|
1
|
+
module Pod
|
2
|
+
class Source
|
3
|
+
|
4
|
+
# Checks whether a podspec can be accepted by a source. The check takes
|
5
|
+
# into account the introduction of 0.0.1 version if there are already
|
6
|
+
# tagged ones or whether there is change in the source.
|
7
|
+
#
|
8
|
+
class Acceptor
|
9
|
+
|
10
|
+
# @return [Source] the source where the podspec should be added.
|
11
|
+
#
|
12
|
+
attr_reader :source
|
13
|
+
|
14
|
+
# @param [Pathname] repo @see Source#repo.
|
15
|
+
#
|
16
|
+
def initialize(repo)
|
17
|
+
@source = Source.new(repo)
|
18
|
+
end
|
19
|
+
|
20
|
+
public
|
21
|
+
|
22
|
+
# @!group Actions
|
23
|
+
#-----------------------------------------------------------------------#
|
24
|
+
|
25
|
+
# Checks whether the given specification can be accepted.
|
26
|
+
#
|
27
|
+
# @return [Array<String>] A list of errors. If the list is empty the
|
28
|
+
# specification should be accepted.
|
29
|
+
#
|
30
|
+
def analyze(spec, previous_spec = nil)
|
31
|
+
errors = []
|
32
|
+
check_spec_source_change(spec, errors)
|
33
|
+
check_if_untagged_version_is_acceptable(spec, errors)
|
34
|
+
check_commit_change_for_untagged_version(spec, previous_spec, errors)
|
35
|
+
check_dependencies(spec, errors)
|
36
|
+
errors
|
37
|
+
end
|
38
|
+
|
39
|
+
# Checks whether the specification at the given path can be accepted.
|
40
|
+
#
|
41
|
+
# @return [Array<String>] A list of errors. If the list is empty the
|
42
|
+
# specification should be accepted.
|
43
|
+
#
|
44
|
+
def analyze_path(spec_path)
|
45
|
+
spec = Specification.from_file(spec_path)
|
46
|
+
analyze(spec)
|
47
|
+
rescue
|
48
|
+
["Unable to load the specification."]
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# @!group Private helpers
|
54
|
+
#-----------------------------------------------------------------------#
|
55
|
+
|
56
|
+
# Checks whether the source of the proposed specification is different
|
57
|
+
# from the one of the reference specification.
|
58
|
+
#
|
59
|
+
# @return [void]
|
60
|
+
#
|
61
|
+
def check_spec_source_change(spec, errors)
|
62
|
+
return unless spec
|
63
|
+
return unless reference_spec(spec)
|
64
|
+
keys = Spec::DSL::SOURCE_KEYS.keys
|
65
|
+
source = spec.source.values_at(*keys).compact.first
|
66
|
+
old_source = reference_spec(spec).source.values_at(*keys).compact.first
|
67
|
+
unless source == old_source
|
68
|
+
errors << "The source of the spec doesn't match with the recorded ones." \
|
69
|
+
"Source: `#{source}`. Previous: `#{old_source}`.\n " \
|
70
|
+
"Please contact the specs repo maintainers if the library changed " \
|
71
|
+
"location."
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Checks there are already tagged specifications if the specification has
|
76
|
+
# a git source and doesn't specify a tag (i.e. rejects 0.0.1 specs if
|
77
|
+
# they are not admissible anymore).
|
78
|
+
#
|
79
|
+
# @return [void]
|
80
|
+
#
|
81
|
+
def check_if_untagged_version_is_acceptable(spec, errors)
|
82
|
+
return if !spec.source[:git] || spec.source[:tag]
|
83
|
+
return unless related_specifications(spec)
|
84
|
+
has_tagged_spec = related_specifications(spec).any? { |s| s.version != '0.0.1' }
|
85
|
+
if has_tagged_spec
|
86
|
+
errors << "There is already at least one versioned specification so " \
|
87
|
+
"untagged versions cannot be accepted."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# If the previous specification for the given file is passed it is
|
92
|
+
# checked for any attempt to update the commit of a 0.0.1 version.
|
93
|
+
#
|
94
|
+
# @return [void]
|
95
|
+
#
|
96
|
+
def check_commit_change_for_untagged_version(spec, previous_spec, errors)
|
97
|
+
return unless previous_spec
|
98
|
+
return unless spec.version == Version.new('0.0.1')
|
99
|
+
unless spec.source[:commit] == previous_spec.source[:commit]
|
100
|
+
errors << "Attempt to rewrite the commit of a 0.0.1 version."
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Checks that there is a specification available for the dependencies of
|
105
|
+
# the given specification.
|
106
|
+
#
|
107
|
+
# @return [void]
|
108
|
+
#
|
109
|
+
def check_dependencies(spec, errors)
|
110
|
+
spec.dependencies.each do |dep|
|
111
|
+
set = source.search(dep)
|
112
|
+
unless set && set.specification
|
113
|
+
errors << "Unable to find a specification for the `#{dep}` dependency."
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
# @!group Source helpers
|
121
|
+
#-----------------------------------------------------------------------#
|
122
|
+
|
123
|
+
# Returns the specifications related to the given spec.
|
124
|
+
#
|
125
|
+
# @param [Specification] spec
|
126
|
+
# The specification for which the siblings specs are needed.
|
127
|
+
#
|
128
|
+
# @return [Array<Specification>] The other specifications of the Pod.
|
129
|
+
#
|
130
|
+
# @return [Nil] If there are no other specifications stored.
|
131
|
+
#
|
132
|
+
def related_specifications(spec)
|
133
|
+
versions = source.versions(spec.name)
|
134
|
+
return unless versions
|
135
|
+
specs = versions.sort.map { |v| source.specification(spec.name, v) }
|
136
|
+
specs.delete(spec)
|
137
|
+
specs
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns the most representative specification for the Pod of the given
|
141
|
+
# spec.
|
142
|
+
#
|
143
|
+
# @param [Specification] spec
|
144
|
+
# The specification for which the representative spec is needed.
|
145
|
+
#
|
146
|
+
# @return [Specification] The specification with the highest version.
|
147
|
+
#
|
148
|
+
# @return [Nil] If there are no other specifications stored.
|
149
|
+
#
|
150
|
+
def reference_spec(spec)
|
151
|
+
specs = related_specifications(spec)
|
152
|
+
specs.last if specs
|
153
|
+
end
|
154
|
+
|
155
|
+
#-----------------------------------------------------------------------#
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
module Pod
|
2
|
+
class Source
|
3
|
+
|
4
|
+
# The Aggregate manages a directory of sources repositories.
|
5
|
+
#
|
6
|
+
class Aggregate
|
7
|
+
|
8
|
+
# @return [Pathname] the directory were the repositories are stored.
|
9
|
+
#
|
10
|
+
attr_reader :repos_dir
|
11
|
+
|
12
|
+
# @param [Pathname] repos_dir @see repos_dir.
|
13
|
+
#
|
14
|
+
def initialize(repos_dir)
|
15
|
+
@repos_dir = repos_dir
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Array<Source>] all the sources.
|
19
|
+
#
|
20
|
+
def all
|
21
|
+
@sources ||= dirs.map { |repo| Source.new(repo) }.sort_by(&:name)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Array<String>] the names of all the pods available.
|
25
|
+
#
|
26
|
+
def all_pods
|
27
|
+
all.map(&:pods).flatten.uniq
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Array<Set>] the sets for all the pods available.
|
31
|
+
#
|
32
|
+
# @note Implementation detail: The sources don't cache their values
|
33
|
+
# because they might change in response to an update. Therefore
|
34
|
+
# this method to prevent slowness caches the values before
|
35
|
+
# processing them.
|
36
|
+
#
|
37
|
+
def all_sets
|
38
|
+
pods_by_source = {}
|
39
|
+
all.each do |source|
|
40
|
+
pods_by_source[source] = source.pods
|
41
|
+
end
|
42
|
+
sources = pods_by_source.keys
|
43
|
+
pods = pods_by_source.values.flatten.uniq
|
44
|
+
|
45
|
+
pods.map do |pod|
|
46
|
+
pod_sources = sources.select{ |s| pods_by_source[s].include?(pod) }.compact
|
47
|
+
Specification::Set.new(pod, pod_sources)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Array<Pathname>] the directories where the sources are stored.
|
52
|
+
#
|
53
|
+
# @note If the repos dir doesn't exits this will return an empty array.
|
54
|
+
#
|
55
|
+
# @raise If the repos dir doesn't exits.
|
56
|
+
#
|
57
|
+
def dirs
|
58
|
+
if repos_dir.exist?
|
59
|
+
repos_dir.children.select(&:directory?)
|
60
|
+
else
|
61
|
+
[]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns a set configured with the source which contains the highest
|
66
|
+
# version in the aggregate.
|
67
|
+
#
|
68
|
+
# @param [String] name
|
69
|
+
# The name of the Pod.
|
70
|
+
#
|
71
|
+
# @return [Set] The most representative set for the Pod with the given
|
72
|
+
# name.
|
73
|
+
#
|
74
|
+
def represenative_set(name)
|
75
|
+
representative_source = nil
|
76
|
+
highest_version = nil
|
77
|
+
all.each do |source|
|
78
|
+
source_versions = source.versions(name)
|
79
|
+
if source_versions
|
80
|
+
source_version = source_versions.first
|
81
|
+
if highest_version.nil? || (highest_version < source_version)
|
82
|
+
highest_version = source_version
|
83
|
+
representative_source = source
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
Specification::Set.new(name, representative_source)
|
88
|
+
end
|
89
|
+
|
90
|
+
public
|
91
|
+
|
92
|
+
# @!group Search
|
93
|
+
#-----------------------------------------------------------------------#
|
94
|
+
|
95
|
+
# @return [Set, nil] a set for a given dependency including all the
|
96
|
+
# {Source} that contain the Pod. If no sources containing the
|
97
|
+
# Pod where found it returns nil.
|
98
|
+
#
|
99
|
+
# @raise If no source including the set can be found.
|
100
|
+
#
|
101
|
+
# @see Source#search
|
102
|
+
#
|
103
|
+
def search(dependency)
|
104
|
+
sources = all.select { |s| !s.search(dependency).nil? }
|
105
|
+
Specification::Set.new(dependency.root_name, sources) unless sources.empty?
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [Array<Set>] the sets that contain the search term.
|
109
|
+
#
|
110
|
+
# @raise If no source including the set can be found.
|
111
|
+
#
|
112
|
+
# @todo Clients should raise not this method.
|
113
|
+
#
|
114
|
+
# @see Source#search_by_name
|
115
|
+
#
|
116
|
+
def search_by_name(query, full_text_search = false)
|
117
|
+
pods_by_source = {}
|
118
|
+
result = []
|
119
|
+
all.each { |s| pods_by_source[s] = s.search_by_name(query, full_text_search).map(&:name) }
|
120
|
+
root_spec_names = pods_by_source.values.flatten.uniq
|
121
|
+
root_spec_names.each do |pod|
|
122
|
+
sources = []
|
123
|
+
pods_by_source.each{ |source, pods| sources << source if pods.include?(pod) }
|
124
|
+
result << Specification::Set.new(pod, sources)
|
125
|
+
end
|
126
|
+
if result.empty?
|
127
|
+
extra = ", author, summary, or description" if full_text_search
|
128
|
+
raise(Informative, "Unable to find a pod with name" \
|
129
|
+
"#{extra} matching `#{query}'")
|
130
|
+
end
|
131
|
+
result
|
132
|
+
end
|
133
|
+
|
134
|
+
public
|
135
|
+
|
136
|
+
# @!group Search Index
|
137
|
+
#-----------------------------------------------------------------------#
|
138
|
+
|
139
|
+
# Generates from scratch the search data for all the sources of the
|
140
|
+
# aggregate. This operation can take a considerable amount of time
|
141
|
+
# (seconds) as it needs to evaluate the most representative podspec
|
142
|
+
# for each Pod.
|
143
|
+
#
|
144
|
+
# @return [Hash{String=>Hash}] The search data of every set grouped by
|
145
|
+
# name.
|
146
|
+
#
|
147
|
+
def generate_search_index
|
148
|
+
result = {}
|
149
|
+
all_sets.each do |set|
|
150
|
+
result[set.name] = search_data_from_set(set)
|
151
|
+
end
|
152
|
+
result
|
153
|
+
end
|
154
|
+
|
155
|
+
# Updates inline the given search data with the information stored in all
|
156
|
+
# the sources. The update skips the Pods for which the version of the
|
157
|
+
# search data is the same of the highest version known to the aggregate.
|
158
|
+
# This can lead to updates in podspecs being skipped until a new version
|
159
|
+
# is released.
|
160
|
+
#
|
161
|
+
# @note This procedure is considerably faster as it only needs to
|
162
|
+
# load the most representative spec of the new or updated Pods.
|
163
|
+
#
|
164
|
+
# @return [Hash{String=>Hash}] The search data of every set grouped by
|
165
|
+
# name.
|
166
|
+
#
|
167
|
+
def update_search_index(search_data)
|
168
|
+
enumerated_names = []
|
169
|
+
all_sets.each do |set|
|
170
|
+
enumerated_names << set.name
|
171
|
+
set_data = search_data[set.name]
|
172
|
+
has_data = set_data && set_data['version']
|
173
|
+
needs_update = !has_data || Version.new(set_data['version']) < set.required_version
|
174
|
+
if needs_update
|
175
|
+
search_data[set.name] = search_data_from_set(set)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
stored_names = search_data.keys
|
180
|
+
delted_names = stored_names - enumerated_names
|
181
|
+
delted_names.each do |name|
|
182
|
+
search_data.delete(name)
|
183
|
+
end
|
184
|
+
|
185
|
+
search_data
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
|
190
|
+
# @!group Private helpers
|
191
|
+
#-----------------------------------------------------------------------#
|
192
|
+
|
193
|
+
# Returns the search related information from the most representative
|
194
|
+
# specification of the set following keys:
|
195
|
+
#
|
196
|
+
# - version
|
197
|
+
# - summary
|
198
|
+
# - description
|
199
|
+
# - authors
|
200
|
+
#
|
201
|
+
# @param [Set] set
|
202
|
+
# The set for which the information is needed.
|
203
|
+
#
|
204
|
+
# @note If the specification can't load an empty hash is returned and
|
205
|
+
# a warning is printed.
|
206
|
+
#
|
207
|
+
# @note For compatibility with non Ruby clients a strings are used
|
208
|
+
# instead of symbols for the keys.
|
209
|
+
#
|
210
|
+
# @return [Hash{String=>String}] A hash with the search information.
|
211
|
+
#
|
212
|
+
def search_data_from_set(set)
|
213
|
+
result = {}
|
214
|
+
spec = set.specification
|
215
|
+
result['version'] = spec.version.to_s
|
216
|
+
result['summary'] = spec.summary
|
217
|
+
result['description'] = spec.description
|
218
|
+
result['authors'] = spec.authors.keys.sort * ', '
|
219
|
+
result
|
220
|
+
rescue
|
221
|
+
CoreUI.warn "Skipping `#{set.name}` because the podspec contains errors."
|
222
|
+
result
|
223
|
+
end
|
224
|
+
|
225
|
+
#-----------------------------------------------------------------------#
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
module Pod
|
2
|
+
class Source
|
3
|
+
|
4
|
+
# Checks a source for errors and warnings.
|
5
|
+
#
|
6
|
+
class HealthReporter
|
7
|
+
|
8
|
+
# @return [Source] the source to check.
|
9
|
+
#
|
10
|
+
attr_reader :source
|
11
|
+
|
12
|
+
# @param [Pathname] repo @see Source#repo.
|
13
|
+
#
|
14
|
+
def initialize(repo)
|
15
|
+
@source = Source.new(repo)
|
16
|
+
@errors = {}
|
17
|
+
@linter_results = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Bool] Whether the more strict validation of the master repo
|
21
|
+
# should be used. Specifically The master repo treats certain
|
22
|
+
# warnings as errors.
|
23
|
+
#
|
24
|
+
attr_accessor :master_repo_mode
|
25
|
+
|
26
|
+
public
|
27
|
+
|
28
|
+
# @!group Configuration
|
29
|
+
#-----------------------------------------------------------------------#
|
30
|
+
|
31
|
+
# Allows to specify an optional callback which is called before
|
32
|
+
# analysing every spec. Suitable for UI.
|
33
|
+
#
|
34
|
+
# @param [Proc] A callback which is called before checking any
|
35
|
+
# specification. It receives the name and the version of the
|
36
|
+
# spec.
|
37
|
+
#
|
38
|
+
# @return [void]
|
39
|
+
#
|
40
|
+
def pre_check(&block)
|
41
|
+
@pre_check_callback = block
|
42
|
+
end
|
43
|
+
|
44
|
+
public
|
45
|
+
|
46
|
+
# @!group Actions
|
47
|
+
#-----------------------------------------------------------------------#
|
48
|
+
|
49
|
+
# Analyzes all the specification files in the source.
|
50
|
+
#
|
51
|
+
# @return [HealthReport] A report which contains the information about the
|
52
|
+
# state of the source.
|
53
|
+
#
|
54
|
+
def analyze
|
55
|
+
@report = HealthReport.new(source)
|
56
|
+
|
57
|
+
source.pods.each do |name|
|
58
|
+
source.versions(name).each do |version|
|
59
|
+
@pre_check_callback.call(name, version) if @pre_check_callback
|
60
|
+
spec_path = source.specification_path(name, version)
|
61
|
+
spec = lint_spec(name, version, spec_path)
|
62
|
+
check_spec_path(name, version, spec) if spec
|
63
|
+
report.analyzed_paths << spec_path
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
check_stray_specs
|
68
|
+
report
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [HealtReport] The report produced by the analysis.
|
72
|
+
#
|
73
|
+
attr_reader :report
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
# @!group Private helpers
|
78
|
+
#-----------------------------------------------------------------------#
|
79
|
+
|
80
|
+
# Checks the validity of the specification with the linter.
|
81
|
+
#
|
82
|
+
# @param [String] name
|
83
|
+
# The name of the Pod.
|
84
|
+
#
|
85
|
+
# @param [Version] version
|
86
|
+
# The version of the specification.
|
87
|
+
#
|
88
|
+
# @param [Pathname] spec_path
|
89
|
+
# The path of the specification to check.
|
90
|
+
#
|
91
|
+
# @return [Specification] The specification loaded by the linter.
|
92
|
+
# @return [Nil] If the specifications raised during evaluation.
|
93
|
+
#
|
94
|
+
def lint_spec(name, version, spec_path)
|
95
|
+
linter = Specification::Linter.new(spec_path)
|
96
|
+
linter.master_repo_mode = master_repo_mode
|
97
|
+
linter.lint
|
98
|
+
linter.results.each do |result|
|
99
|
+
type = result.type == :error ? :error : :warning
|
100
|
+
report.add_message(type, result.message, name, version)
|
101
|
+
end
|
102
|
+
linter.spec
|
103
|
+
end
|
104
|
+
|
105
|
+
# Ensures that the name and the version of the specification correspond
|
106
|
+
# to the ones expected by the repo given its path.
|
107
|
+
#
|
108
|
+
# @param [String] name
|
109
|
+
# The name of the Pod.
|
110
|
+
#
|
111
|
+
# @param [Version] version
|
112
|
+
# The version of the specification.
|
113
|
+
#
|
114
|
+
# @param [Specification] spec
|
115
|
+
# The specification to check.
|
116
|
+
#
|
117
|
+
# @return [void]
|
118
|
+
#
|
119
|
+
def check_spec_path(name, version, spec)
|
120
|
+
unless spec.name == name && spec.version == version
|
121
|
+
report.add_message(:error, "Incorrect path", name)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Checks for any stray specification in the repo.
|
126
|
+
#
|
127
|
+
# @param [Array<Pathname>] analyzed_paths
|
128
|
+
# The specification to check.
|
129
|
+
#
|
130
|
+
# @return [void]
|
131
|
+
#
|
132
|
+
def check_stray_specs
|
133
|
+
all_paths = Pathname.glob(source.repo + '**/*.podspec{,.yaml}')
|
134
|
+
stray_specs = all_paths - report.analyzed_paths
|
135
|
+
stray_specs.each do |path|
|
136
|
+
report.add_message(:error, "Stray spec", path)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
#-----------------------------------------------------------------------#
|
141
|
+
|
142
|
+
# Encapsulates the information about the state of a repo.
|
143
|
+
#
|
144
|
+
class HealthReport
|
145
|
+
|
146
|
+
# @return [Source] the source analyzed.
|
147
|
+
#
|
148
|
+
attr_reader :source
|
149
|
+
|
150
|
+
# @param [Source] @see source.
|
151
|
+
#
|
152
|
+
def initialize(source)
|
153
|
+
@source = source
|
154
|
+
@analyzed_paths = []
|
155
|
+
@pods_by_error = {}
|
156
|
+
@pods_by_warning = {}
|
157
|
+
end
|
158
|
+
|
159
|
+
# @return [Array<Pathname>] The list of the analyzed paths.
|
160
|
+
#
|
161
|
+
attr_accessor :analyzed_paths
|
162
|
+
|
163
|
+
# @return [Hash{ String => Hash }] The pods (the version grouped by
|
164
|
+
# name) grouped by an error message.
|
165
|
+
#
|
166
|
+
attr_accessor :pods_by_error
|
167
|
+
|
168
|
+
# @return [Hash{ String => Hash }] The pods (the version grouped by
|
169
|
+
# name) grouped by a warning message.
|
170
|
+
#
|
171
|
+
attr_accessor :pods_by_warning
|
172
|
+
|
173
|
+
# Adds a message with the given type for the specification with the
|
174
|
+
# given name and version.
|
175
|
+
#
|
176
|
+
# @param [Symbol] type
|
177
|
+
# The type of message. Either `:error` or `:warning`.
|
178
|
+
#
|
179
|
+
# @param [String] message
|
180
|
+
# The contents of the message.
|
181
|
+
#
|
182
|
+
# @param [String] spec_name
|
183
|
+
# The name of the Pod.
|
184
|
+
#
|
185
|
+
# @param [String] spec_version
|
186
|
+
# The version of the specification.
|
187
|
+
#
|
188
|
+
# @return [void]
|
189
|
+
#
|
190
|
+
def add_message(type, message, spec_name, spec_version = nil)
|
191
|
+
if type == :error
|
192
|
+
pods_by_error[message] ||= {}
|
193
|
+
pods_by_error[message][spec_name] ||= []
|
194
|
+
pods_by_error[message][spec_name] << spec_version
|
195
|
+
else
|
196
|
+
pods_by_warning[message] ||= {}
|
197
|
+
pods_by_warning[message][spec_name] ||= []
|
198
|
+
pods_by_warning[message][spec_name] << spec_version
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
#-----------------------------------------------------------------------#
|
204
|
+
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|