Module: Bibliothecary::Analyser::Analysis

Defined in:
lib/bibliothecary/analyser/analysis.rb

Instance Method Summary collapse

Instance Method Details

#analyse(folder_path, file_list, options: {}) ⇒ Object Also known as: analyze

Convenience method to create FileInfo objects from folder path and file list.

Parameters:

  • folder_path (String)
  • file_list (Array<String>)
  • options (Hash) (defaults to: {})


12
13
14
# File 'lib/bibliothecary/analyser/analysis.rb', line 12

def analyse(folder_path, file_list, options: {})
  analyse_file_info(file_list.map { |full_path| FileInfo.new(folder_path, full_path) }, options: options)
end

#analyse_contents(filename, contents, options: {}) ⇒ Object Also known as: analyze_contents



31
32
33
# File 'lib/bibliothecary/analyser/analysis.rb', line 31

def analyse_contents(filename, contents, options: {})
  analyse_contents_from_info(FileInfo.new(nil, filename, contents), options: options)
end

#analyse_contents_from_info(info, options: {}) ⇒ Object Also known as: analyze_contents_from_info

This is the place a parsing operation will eventually end up.

Parameters:



39
40
41
42
43
44
45
46
47
48
# File 'lib/bibliothecary/analyser/analysis.rb', line 39

def analyse_contents_from_info(info, options: {})
  # 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, options: options)

  dependencies_to_analysis(info, kind, dependencies)
rescue Bibliothecary::FileParsingError => e
  Bibliothecary::Analyser.create_error_analysis(platform_name, info.relative_path, kind, e.message, e.location)
end

#analyse_file_info(file_info_list, options: {}) ⇒ Object Also known as: analyze_file_info

Analyze a set of FileInfo objects and extract manifests from them all.



20
21
22
23
24
25
26
27
28
# File 'lib/bibliothecary/analyser/analysis.rb', line 20

def analyse_file_info(file_info_list, options: {})
  matching_info = file_info_list
    .select(&method(:match_info?))

  matching_info.flat_map do |info|
    analyse_contents_from_info(info, options: options)
      .merge(related_paths: related_paths(info, matching_info))
  end
end

#dependencies_to_analysis(info, kind, dependencies) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/bibliothecary/analyser/analysis.rb', line 51

def dependencies_to_analysis(info, kind, dependencies)
  dependencies ||= [] # work around any legacy parsers that return nil
  if generic?
    grouped = dependencies.group_by { |dep| dep[:platform] }
    all_analyses = grouped.keys.map do |platform|
      deplatformed_dependencies = grouped[platform].map do |d|
        d.delete(:platform)
        d
      end
      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

#parse_file(filename, contents, options: {}) ⇒ Object

Call the matching parse class method for this file with these contents



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/bibliothecary/analyser/analysis.rb', line 75

def parse_file(filename, contents, options: {})
  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, options: options.merge(filename: filename))
rescue Exception => e # default is StandardError but C bindings throw Exceptions # rubocop:disable Lint/RescueException
  # the C xml parser also puts a newline at the end of the message
  location = e.backtrace_locations[0]
    .to_s
    .then { |l| l =~ /bibliothecary\// ? l.split("bibliothecary/").last : l.split("gems/").last }
  raise Bibliothecary::FileParsingError.new(e.message.strip, filename, location)
end