Class: Debendencies

Inherits:
Object
  • Object
show all
Defined in:
lib/debendencies.rb,
lib/debendencies/cli.rb,
lib/debendencies/utils.rb,
lib/debendencies/errors.rb,
lib/debendencies/version.rb,
lib/debendencies/elf_analysis.rb,
lib/debendencies/package_finding.rb,
lib/debendencies/package_version.rb,
lib/debendencies/package_dependency.rb,
lib/debendencies/symbols_file_parsing.rb

Defined Under Namespace

Modules: Private Classes: CLI, Error, PackageDependency, VersionConstraint

Constant Summary collapse

VERSION_STRING =
"1.1.0"

Instance Method Summary collapse

Constructor Details

#initialize(logger: nil) ⇒ Debendencies

Returns a new instance of Debendencies.



10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/debendencies.rb', line 10

def initialize(logger: nil)
  @logger = logger

  # Shared libraries (sonames) that have been scanned.
  @scanned_libs = Set.new

  # Shared libraries (sonames) that the scanned ELF files depend on.
  # Maps each soname to an array of ELF file path that depend on it (the dependents).
  @dependency_libs = {}

  @symbol_extraction_cache = {}
end

Instance Method Details

#resolveArray<PackageDependency>

Resolves the Debian package dependencies of all scanned ELF files. Returns an array of PackageDependency objects:

[
  PackageDependency.new('libc6', [VersionConstraint.new('>=', '2.28')]),
  PackageDependency.new('libfoo1'),
]

Returns:



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

def resolve
  result = []

  @dependency_libs.each_pair do |dependency_soname, dependent_elf_file_paths|
    # ELF files in a package could depend on libraries included in the same package,
    # so omit resolving scanned libraries.
    if @scanned_libs.include?(dependency_soname)
      @logger&.info("Skipping dependency resolution for scanned library: #{dependency_soname}")
      next
    end

    package_name = Private.find_package_providing_lib(dependency_soname)
    raise Error, "Error resolving package dependencies: no package provides #{dependency_soname}" if package_name.nil?
    @logger&.info("Resolved package providing #{dependency_soname}: #{package_name}")
    version_constraints = maybe_create_version_constraints(package_name, dependency_soname, dependent_elf_file_paths)
    @logger&.info("Resolved version constraints: #{version_constraints&.map { |vc| vc.as_json }.inspect}")

    result << PackageDependency.new(package_name, version_constraints)
  end

  result.uniq!
  result
end

#scan(*paths) ⇒ Object



23
24
25
26
27
28
29
30
31
# File 'lib/debendencies.rb', line 23

def scan(*paths)
  paths.each do |path|
    if File.directory?(path)
      scan_directory(path)
    else
      scan_file(path)
    end
  end
end