Module: Bibliothecary::Analyser::ClassMethods

Defined in:
lib/bibliothecary/analyser.rb

Instance Method Summary collapse

Instance Method Details

#analyse(folder_path, file_list) ⇒ Object



101
102
103
# File 'lib/bibliothecary/analyser.rb', line 101

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



115
116
117
# File 'lib/bibliothecary/analyser.rb', line 115

def analyse_contents(filename, contents)
  analyse_contents_from_info(FileInfo.new(nil, filename, contents))
end

#analyse_contents_from_info(info) ⇒ Object



119
120
121
122
123
124
125
126
127
128
# File 'lib/bibliothecary/analyser.rb', line 119

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)

  Bibliothecary::Analyser::create_analysis(platform_name, info.relative_path, kind, dependencies || [])
rescue Bibliothecary::FileParsingError => e
  Bibliothecary::Analyser::create_error_analysis(platform_name, info.relative_path, kind, e.message)
end

#analyse_file_info(file_info_list) ⇒ Object



105
106
107
108
109
110
111
112
113
# File 'lib/bibliothecary/analyser.rb', line 105

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: related_paths(info, matching_info))
  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



143
144
145
# File 'lib/bibliothecary/analyser.rb', line 143

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



147
148
149
150
# File 'lib/bibliothecary/analyser.rb', line 147

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



132
133
134
# File 'lib/bibliothecary/analyser.rb', line 132

def determine_kind(filename, contents = nil)
  determine_kind_from_info(FileInfo.new(nil, filename, contents))
end

#determine_kind_from_info(info) ⇒ Object



136
137
138
139
# File 'lib/bibliothecary/analyser.rb', line 136

def determine_kind_from_info(info)
  first_matching_mapping_details(info)
    .fetch(:kind, nil)
end

#map_dependencies(hash, key, type) ⇒ Object



91
92
93
94
95
96
97
98
99
# File 'lib/bibliothecary/analyser.rb', line 91

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

Returns:

  • (Boolean)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/bibliothecary/analyser.rb', line 28

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.

Returns:

  • (Boolean)


69
70
71
# File 'lib/bibliothecary/analyser.rb', line 69

def match?(filename, contents = nil)
  match_info?(FileInfo.new(nil, filename, contents))
end

#match_extension(filename, case_insensitive: false) ⇒ Object



182
183
184
185
186
187
188
# File 'lib/bibliothecary/analyser.rb', line 182

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



167
168
169
170
171
172
173
# File 'lib/bibliothecary/analyser.rb', line 167

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



175
176
177
178
179
180
# File 'lib/bibliothecary/analyser.rb', line 175

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

Returns:

  • (Boolean)


73
74
75
# File 'lib/bibliothecary/analyser.rb', line 73

def match_info?(info)
  first_matching_mapping_details(info).any?
end

#parse_file(filename, contents) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/bibliothecary/analyser.rb', line 43

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.message.strip, filename)
end

#parse_json_runtime_manifest(file_contents) ⇒ Object



81
82
83
84
85
86
87
88
89
# File 'lib/bibliothecary/analyser.rb', line 81

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



152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/bibliothecary/analyser.rb', line 152

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_nameObject



77
78
79
# File 'lib/bibliothecary/analyser.rb', line 77

def platform_name
  self.name.to_s.split('::').last.downcase
end