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) ⇒ Runner

Returns a new instance of Runner.



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

def initialize(configuration)
  @configuration = configuration
  @options = {
    cache: {},
  }
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.package_manager.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 = package_managers.map do |pm|
    matching_infos = info_list.select { |info| info.package_manager == pm }
    pm.analyse_file_info(matching_infos, options: @options)
  end
  analyses = analyses.flatten.compact

  info_list.select { |info| info.package_manager.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.



120
121
122
123
124
125
126
# File 'lib/bibliothecary/runner.rb', line 120

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

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

#applicable_package_managers(info) ⇒ Object



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

def applicable_package_managers(info)
  managers = package_managers.select { |pm| pm.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.



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

def filter_multi_manifest_entries(path, related_files_info_entries)
  MultiManifestFilter.new(path: path, related_files_info_entries: related_files_info_entries, runner: self).results
end

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

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



102
103
104
# File 'lib/bibliothecary/runner.rb', line 102

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

#find_manifests_from_contents(file_path_contents_hash) ⇒ Object

file_path_contents_hash contains an Array of { file_path, contents }



111
112
113
114
115
116
117
# File 'lib/bibliothecary/runner.rb', line 111

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.package_manager.nil? }
  )
end

#find_manifests_from_paths(paths) ⇒ Object



106
107
108
# File 'lib/bibliothecary/runner.rb', line 106

def find_manifests_from_paths(paths)
  RelatedFilesInfo.create_from_file_infos(load_file_info_list_from_paths(paths).reject { |info| info.package_manager.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.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/bibliothecary/runner.rb', line 134

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) }
  package_managers.map do |pm|
    # (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
      pm.match?(file_path)
    end
  end.flatten.uniq.compact
end

#ignored_dirsObject



150
151
152
# File 'lib/bibliothecary/runner.rb', line 150

def ignored_dirs
  @configuration.ignored_dirs
end

#ignored_filesObject



154
155
156
# File 'lib/bibliothecary/runner.rb', line 154

def ignored_files
  @configuration.ignored_files
end

#load_file_info_list(path) ⇒ Object



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

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_package_managers_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:



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/bibliothecary/runner.rb', line 55

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_package_managers_for_file_to_list(file_list, info)
  end

  file_list
end

#load_file_info_list_from_paths(paths) ⇒ Object



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

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_package_managers_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



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

def package_managers
  Bibliothecary::Parsers.constants.map { |c| Bibliothecary::Parsers.const_get(c) }.sort_by { |c| c.to_s.downcase }
end