Module: Bibliothecary::Analyser::ClassMethods
- Defined in:
- lib/bibliothecary/analyser.rb
Instance Method Summary collapse
- #analyse(folder_path, file_list) ⇒ Object (also: #analyze)
- #analyse_contents(filename, contents) ⇒ Object (also: #analyze_contents)
- #analyse_contents_from_info(info) ⇒ Object (also: #analyze_contents_from_info)
- #analyse_file_info(file_info_list) ⇒ Object (also: #analyze_file_info)
- #dependencies_to_analysis(info, kind, dependencies) ⇒ Object
-
#determine_can_have_lockfile(filename, contents = nil) ⇒ Object
calling this with contents=nil can produce less-informed results, but kept for back compat.
- #determine_can_have_lockfile_from_info(info) ⇒ Object
-
#determine_kind(filename, contents = nil) ⇒ Object
calling this with contents=nil can produce less-informed results, but kept for back compat.
- #determine_kind_from_info(info) ⇒ Object
- #generic? ⇒ Boolean
- #map_dependencies(hash, key, type) ⇒ Object
- #mapping_entry_match?(matcher, details, info) ⇒ Boolean
-
#match?(filename, contents = nil) ⇒ Boolean
this is broken with contents=nil because it can’t look at file contents, so skips manifests that are ambiguously a manifest considering only the filename.
- #match_extension(filename, case_insensitive: false) ⇒ Object
- #match_filename(filename, case_insensitive: false) ⇒ Object
- #match_filenames(*filenames) ⇒ Object
- #match_info?(info) ⇒ Boolean
- #parse_file(filename, contents) ⇒ Object
- #parse_json_runtime_manifest(file_contents) ⇒ Object
- #parse_ruby_manifest(manifest) ⇒ Object
- #platform_name ⇒ Object
Instance Method Details
#analyse(folder_path, file_list) ⇒ Object Also known as: analyze
105 106 107 |
# File 'lib/bibliothecary/analyser.rb', line 105 def analyse(folder_path, file_list) analyse_file_info(file_list.map { |full_path| FileInfo.new(folder_path, full_path) }) end |
#analyse_contents(filename, contents) ⇒ Object Also known as: analyze_contents
121 122 123 |
# File 'lib/bibliothecary/analyser.rb', line 121 def analyse_contents(filename, contents) analyse_contents_from_info(FileInfo.new(nil, filename, contents)) end |
#analyse_contents_from_info(info) ⇒ Object Also known as: analyze_contents_from_info
145 146 147 148 149 150 151 152 153 154 |
# File 'lib/bibliothecary/analyser.rb', line 145 def analyse_contents_from_info(info) # If your Parser needs to return multiple responses for one file, please override this method # For example see conda.rb kind = determine_kind_from_info(info) dependencies = parse_file(info.relative_path, info.contents) dependencies_to_analysis(info, kind, dependencies) rescue Bibliothecary::FileParsingError => e Bibliothecary::Analyser::create_error_analysis(platform_name, info.relative_path, kind, e.) end |
#analyse_file_info(file_info_list) ⇒ Object Also known as: analyze_file_info
110 111 112 113 114 115 116 117 118 |
# File 'lib/bibliothecary/analyser.rb', line 110 def analyse_file_info(file_info_list) matching_info = file_info_list .select(&method(:match_info?)) matching_info.flat_map do |info| analyse_contents_from_info(info) .merge(related_paths: (info, matching_info)) end end |
#dependencies_to_analysis(info, kind, dependencies) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/bibliothecary/analyser.rb', line 126 def dependencies_to_analysis(info, kind, dependencies) dependencies = dependencies || [] # work around any legacy parsers that return nil if generic? analyses = [] grouped = dependencies.group_by { |dep| dep[:platform] } all_analyses = grouped.keys.map do |platform| deplatformed_dependencies = grouped[platform].map { |d| d.delete(:platform); d } Bibliothecary::Analyser::create_analysis(platform, info.relative_path, kind, deplatformed_dependencies) end # this is to avoid a larger refactor for the time being. The larger refactor # needs to make analyse_contents return multiple analysis, or add another # method that can return multiple and deprecate analyse_contents, perhaps. raise "File contains zero or multiple platforms, currently must have exactly one" if all_analyses.length != 1 all_analyses.first else Bibliothecary::Analyser::create_analysis(platform_name, info.relative_path, kind, dependencies) end end |
#determine_can_have_lockfile(filename, contents = nil) ⇒ Object
calling this with contents=nil can produce less-informed results, but kept for back compat
170 171 172 |
# File 'lib/bibliothecary/analyser.rb', line 170 def determine_can_have_lockfile(filename, contents = nil) determine_can_have_lockfile_from_info(FileInfo.new(nil, filename, contents)) end |
#determine_can_have_lockfile_from_info(info) ⇒ Object
174 175 176 177 |
# File 'lib/bibliothecary/analyser.rb', line 174 def determine_can_have_lockfile_from_info(info) first_matching_mapping_details(info) .fetch(:can_have_lockfile, true) end |
#determine_kind(filename, contents = nil) ⇒ Object
calling this with contents=nil can produce less-informed results, but kept for back compat
159 160 161 |
# File 'lib/bibliothecary/analyser.rb', line 159 def determine_kind(filename, contents = nil) determine_kind_from_info(FileInfo.new(nil, filename, contents)) end |
#determine_kind_from_info(info) ⇒ Object
163 164 165 166 |
# File 'lib/bibliothecary/analyser.rb', line 163 def determine_kind_from_info(info) first_matching_mapping_details(info) .fetch(:kind, nil) end |
#generic? ⇒ Boolean
28 29 30 |
# File 'lib/bibliothecary/analyser.rb', line 28 def generic? platform_name == "generic" end |
#map_dependencies(hash, key, type) ⇒ Object
95 96 97 98 99 100 101 102 103 |
# File 'lib/bibliothecary/analyser.rb', line 95 def map_dependencies(hash, key, type) hash.fetch(key,[]).map do |name, requirement| { name: name, requirement: requirement, type: type } end end |
#mapping_entry_match?(matcher, details, info) ⇒ Boolean
32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/bibliothecary/analyser.rb', line 32 def mapping_entry_match?(matcher, details, info) if matcher.call(info.relative_path) # we only want to load contents if we don't have them already # and there's a content_matcher method to use return true if details[:content_matcher].nil? # this is the libraries.io case where we won't load all .xml # files (for example) just to look at their contents, we'll # assume they are not manifests. return false if info.contents.nil? return send(details[:content_matcher], info.contents) else return false end end |
#match?(filename, contents = nil) ⇒ Boolean
this is broken with contents=nil because it can’t look at file contents, so skips manifests that are ambiguously a manifest considering only the filename. However, those are the semantics that libraries.io uses since it doesn’t have the files locally.
73 74 75 |
# File 'lib/bibliothecary/analyser.rb', line 73 def match?(filename, contents = nil) match_info?(FileInfo.new(nil, filename, contents)) end |
#match_extension(filename, case_insensitive: false) ⇒ Object
209 210 211 212 213 214 215 |
# File 'lib/bibliothecary/analyser.rb', line 209 def match_extension(filename, case_insensitive: false) if case_insensitive lambda { |path| path.downcase.end_with?(filename.downcase) } else lambda { |path| path.end_with?(filename) } end end |
#match_filename(filename, case_insensitive: false) ⇒ Object
194 195 196 197 198 199 200 |
# File 'lib/bibliothecary/analyser.rb', line 194 def match_filename(filename, case_insensitive: false) if case_insensitive lambda { |path| path.downcase == filename.downcase || path.downcase.end_with?("/" + filename.downcase) } else lambda { |path| path == filename || path.end_with?("/" + filename) } end end |
#match_filenames(*filenames) ⇒ Object
202 203 204 205 206 207 |
# File 'lib/bibliothecary/analyser.rb', line 202 def match_filenames(*filenames) lambda do |path| filenames.any? { |f| path == f } || filenames.any? { |f| path.end_with?("/" + f) } end end |
#match_info?(info) ⇒ Boolean
77 78 79 |
# File 'lib/bibliothecary/analyser.rb', line 77 def match_info?(info) first_matching_mapping_details(info).any? end |
#parse_file(filename, contents) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/bibliothecary/analyser.rb', line 47 def parse_file(filename, contents) details = first_matching_mapping_details(FileInfo.new(nil, filename, contents)) # this can be raised if we don't check match?/match_info?, # OR don't have the file contents when we check them, so # it turns out for example that a .xml file isn't a # manifest after all. raise Bibliothecary::FileParsingError.new("No parser for this file type", filename) unless details[:parser] # The `parser` method should raise an exception if the file is malformed, # should return empty [] if the file is fine but simply doesn't contain # any dependencies, and should never return nil. At the time of writing # this comment, some of the parsers return [] or nil to mean an error # which is confusing to users. send(details[:parser], contents) rescue Exception => e # default is StandardError but C bindings throw Exceptions # the C xml parser also puts a newline at the end of the message raise Bibliothecary::FileParsingError.new(e..strip, filename) end |
#parse_json_runtime_manifest(file_contents) ⇒ Object
85 86 87 88 89 90 91 92 93 |
# File 'lib/bibliothecary/analyser.rb', line 85 def parse_json_runtime_manifest(file_contents) JSON.parse(file_contents).fetch('dependencies',[]).map do |name, requirement| { name: name, requirement: requirement, type: 'runtime' } end end |
#parse_ruby_manifest(manifest) ⇒ Object
179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/bibliothecary/analyser.rb', line 179 def parse_ruby_manifest(manifest) manifest.dependencies.inject([]) do |deps, dep| deps.push({ name: dep.name, requirement: dep .requirement .requirements .sort_by(&:last) .map { |op, version| "#{op} #{version}" } .join(", "), type: dep.type }) end.uniq end |
#platform_name ⇒ Object
81 82 83 |
# File 'lib/bibliothecary/analyser.rb', line 81 def platform_name self.name.to_s.split('::').last.downcase end |