Class: Bibliothecary::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/bibliothecary/runner.rb,
lib/bibliothecary/runner/multi_manifest_filter.rb

Overview

A class that allows bibliothecary to run with multiple configurations at once, rather than with one global. A runner is created every time a file is targeted to be parsed. Don’t call parse methods directory! Use a Runner.

Defined Under Namespace

Classes: MultiManifestFilter

Instance Method Summary collapse

Constructor Details

#initialize(configuration, parser_options: {}) ⇒ Runner

Returns a new instance of Runner.



8
9
10
11
12
13
# File 'lib/bibliothecary/runner.rb', line 8

def initialize(configuration, parser_options: {})
  @configuration = configuration
  @options = {
    cache: {},
  }.merge(parser_options)
end

Instance Method Details

#analyse(path, ignore_unparseable_files: true) ⇒ Object Also known as: analyze



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/bibliothecary/runner.rb', line 15

def analyse(path, ignore_unparseable_files: true)
  info_list = load_file_info_list(path)

  info_list = info_list.reject { |info| info.parser.nil? } if ignore_unparseable_files

  # Each package manager needs to see its entire list so it can
  # associate related manifests and lockfiles for example.
  analyses = parsers.map do |p|
    matching_infos = info_list.select { |info| info.parser == p }
    p.analyse_file_info(matching_infos, options: @options)
  end
  analyses = analyses.flatten.compact

  info_list.select { |info| info.parser.nil? }.each do |info|
    analyses.push(Bibliothecary::Analyser.create_error_analysis("unknown", info.relative_path, "unknown",
                                                                "No parser for this file type"))
  end

  analyses
end

#analyse_file(file_path, contents) ⇒ Object Also known as: analyze_file

Read a manifest file and extract the list of dependencies from that file.



133
134
135
136
137
138
139
# File 'lib/bibliothecary/runner.rb', line 133

def analyse_file(file_path, contents)
  contents = Bibliothecary.utf8_string(contents)

  parsers.select { |p| p.match?(file_path, contents) }.map do |p|
    p.analyse_contents(file_path, contents, options: @options)
  end.flatten.uniq.compact
end

#applicable_package_managers(_info) ⇒ Object



42
43
44
# File 'lib/bibliothecary/runner.rb', line 42

def applicable_package_managers(_info)
  raise "Runner#applicable_package_managers() has been removed in bibliothecary 15.0.0. Use applicable_parsers() instead, which now includes MultiParsers."
end

#applicable_parsers(info) ⇒ Object



46
47
48
49
# File 'lib/bibliothecary/runner.rb', line 46

def applicable_parsers(info)
  managers = parsers.select { |p| p.match_info?(info) }
  managers.empty? ? [nil] : managers
end

#filter_multi_manifest_entries(_path, _related_files_info_entries) ⇒ Object

We don’t know what file groups are in multi file manifests until we process them. In those cases, process those, then reject the RelatedFilesInfo objects that aren’t in the manifest.

This means we’re likely analyzing these files twice in processing, but we need that accurate package manager information.



177
178
179
# File 'lib/bibliothecary/runner.rb', line 177

def filter_multi_manifest_entries(_path, _related_files_info_entries)
  raise "Bibliothecary::Runner#filter_multi_manifest_entries() has been removed in bibliothecary 15.0.0. Since MultiParsers now act like Parsers, there is no replacement or need for it."
end

#find_manifests(path) ⇒ Array<Bibliothecary::RelatedFilesInfo>

Get a list of files in this path grouped by filename and repeated by package manager.



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

def find_manifests(path)
  RelatedFilesInfo.create_from_file_infos(load_file_info_list(path).reject { |info| info.parser.nil? })
end

#find_manifests_from_contents(file_path_contents_hash) ⇒ Object

file_path_contents_hash contains an Array of { file_path, contents }



124
125
126
127
128
129
130
# File 'lib/bibliothecary/runner.rb', line 124

def find_manifests_from_contents(file_path_contents_hash)
  RelatedFilesInfo.create_from_file_infos(
    load_file_info_list_from_contents(
      file_path_contents_hash
    ).reject { |info| info.parser.nil? }
  )
end

#find_manifests_from_paths(paths) ⇒ Object



119
120
121
# File 'lib/bibliothecary/runner.rb', line 119

def find_manifests_from_paths(paths)
  RelatedFilesInfo.create_from_file_infos(load_file_info_list_from_paths(paths).reject { |info| info.parser.nil? })
end

#identify_manifests(file_list) ⇒ Object

this skips manifests sometimes because it doesn’t look at file contents and can’t establish from only regexes that the thing is a manifest. We exclude rather than include ambiguous filenames because this API is used by libraries.io and we don’t want to download all .xml files from GitHub.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/bibliothecary/runner.rb', line 147

def identify_manifests(file_list)
  ignored_dirs_with_slash = ignored_dirs.map { |d| d.end_with?("/") ? d : "#{d}/" }
  allowed_file_list = file_list.reject do |f|
    ignored_dirs.include?(f) || f.start_with?(*ignored_dirs_with_slash)
  end
  allowed_file_list = allowed_file_list.reject { |f| ignored_files.include?(f) }
  parsers.map do |p|
    # (skip rubocop false positive, since match? is a custom method)
    allowed_file_list.select do |file_path| # rubocop:disable Style/SelectByRegexp
      # this is a call to match? without file contents, which will skip
      # ambiguous filenames that are only possibly a manifest
      p.match?(file_path)
    end
  end.flatten.uniq.compact
end

#ignored_dirsObject



163
164
165
# File 'lib/bibliothecary/runner.rb', line 163

def ignored_dirs
  @configuration.ignored_dirs
end

#ignored_filesObject



167
168
169
# File 'lib/bibliothecary/runner.rb', line 167

def ignored_files
  @configuration.ignored_files
end

#load_file_info_list(path) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/bibliothecary/runner.rb', line 96

def load_file_info_list(path)
  file_list = []

  Find.find(path) do |subpath|
    info = FileInfo.new(path, subpath)

    Find.prune if FileTest.directory?(subpath) && ignored_dirs.include?(info.relative_path)
    next unless FileTest.file?(subpath)
    next if ignored_files.include?(info.relative_path)

    add_matching_parsers_for_file_to_list(file_list, info)
  end

  file_list
end

#load_file_info_list_from_contents(file_path_contents_hash) ⇒ Array<Bibliothecary::FileInfo>

Parses an array of format [“”, contents: “”,] to match on both filename matches and on content_match patterns.

Returns:



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/bibliothecary/runner.rb', line 68

def load_file_info_list_from_contents(file_path_contents_hash)
  file_list = []

  file_path_contents_hash.each do |file|
    info = FileInfo.new(nil, file[:file_path], file[:contents])

    next if ignored_files.include?(info.relative_path)

    add_matching_parsers_for_file_to_list(file_list, info)
  end

  file_list
end

#load_file_info_list_from_paths(paths) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/bibliothecary/runner.rb', line 82

def load_file_info_list_from_paths(paths)
  file_list = []

  paths.each do |path|
    info = FileInfo.new(nil, path)

    next if ignored_files.include?(info.relative_path)

    add_matching_parsers_for_file_to_list(file_list, info)
  end

  file_list
end

#load_file_list(path) ⇒ Object

deprecated; use load_file_info_list.



38
39
40
# File 'lib/bibliothecary/runner.rb', line 38

def load_file_list(path)
  load_file_info_list(path).map(&:full_path)
end

#package_managersObject



51
52
53
# File 'lib/bibliothecary/runner.rb', line 51

def package_managers
  raise "Runner#applicable_package_managers() has been removed in bibliothecary 15.0.0. Use applicable_parsers() instead, which now includes MultiParsers."
end

#parsersObject



55
56
57
58
59
60
61
62
# File 'lib/bibliothecary/runner.rb', line 55

def parsers
  [Bibliothecary::Parsers, Bibliothecary::MultiParsers]
    .flat_map do |mod|
      mod.constants
        .map { |c| mod.const_get(c) }
        .sort_by { |c| c.to_s.downcase }
    end
end