class Bundler::Audit::Database

Represents the directory of advisories, grouped by gem name and CVE number.

Constants

DEFAULT_PATH

Default path to the ruby-advisory-db.

@since 0.8.0

URL

Git URL of the ruby-advisory-db.

USER_PATH

Path to the user’s copy of the ruby-advisory-db.

Attributes

path[R]

The path to the advisory database.

@return [String]

Public Class Methods

download(options={}) click to toggle source

Downloads the ruby-advisory-db.

@param [Hash] options

Additional options.

@option options [String] :path (DEFAULT_PATH)

The destination path for the new ruby-advisory-db.

@option options [Boolean] :quiet

Specify whether `git` should be `--quiet`.

@return [Dataase]

The newly downloaded database.

@raise [DownloadFailed]

Indicates that the download failed.

@note

Requires network access.

@since 0.8.0

# File lib/bundler/audit/database.rb, line 117
def self.download(options={})
  unless (options.keys - [:path, :quiet]).empty?
    raise(ArgumentError,"Invalid option(s)")
  end

  path = options.fetch(:path,DEFAULT_PATH)

  command = %w[git clone]
  command << '--quiet' if options[:quiet]
  command << URL << path

  unless system(*command)
    raise(DownloadFailed,"failed to download #{URL} to #{path.inspect}")
  end

  return new(path)
end
exists?(path=DEFAULT_PATH) click to toggle source

Tests whether the database exists.

@param [String] path

The given path of the database to check.

@return [Boolean]

@since 0.8.0

# File lib/bundler/audit/database.rb, line 90
def self.exists?(path=DEFAULT_PATH)
  File.directory?(path) && !(Dir.entries(path) - %w[. ..]).empty?
end
new(path=self.class.path) click to toggle source

Initializes the Advisory Database.

@param [String] path

The path to the advisory database.

@raise [ArgumentError]

The path was not a directory.
# File lib/bundler/audit/database.rb, line 62
def initialize(path=self.class.path)
  unless File.directory?(path)
    raise(ArgumentError,"#{path.dump} is not a directory")
  end

  @path = path
end
path() click to toggle source

The default path for the database.

@return [String]

The path to the database directory.
# File lib/bundler/audit/database.rb, line 76
def self.path
  DEFAULT_PATH
end
update!(options={}) click to toggle source

Updates the ruby-advisory-db.

@param [Hash] options

Additional options.

@option options [Boolean] :quiet

Specify whether `git` should be `--quiet`.

@return [Boolean]

Specifies whether the update was successful.

@raise [ArgumentError]

Invalid options were given.

@note

Requires network access.

@since 0.3.0

@deprecated Use {#update!} instead.

# File lib/bundler/audit/database.rb, line 157
def self.update!(options={})
  raise "Invalid option(s)" unless (options.keys - [:quiet]).empty?

  if File.directory?(DEFAULT_PATH)
    begin
      new(DEFAULT_PATH).update!(options)
    rescue UpdateFailed then false
    end
  else
    begin
      download(options.merge(path: DEFAULT_PATH))
    rescue DownloadFailed then false
    end
  end
end

Public Instance Methods

advisories() { |load| ... } click to toggle source

Enumerates over every advisory in the database.

@yield [advisory]

If a block is given, it will be passed each advisory.

@yieldparam [Advisory] advisory

An advisory from the database.

@return [Enumerator]

If no block is given, an Enumerator will be returned.
# File lib/bundler/audit/database.rb, line 265
def advisories(&block)
  return enum_for(__method__) unless block_given?

  each_advisory_path do |path|
    yield Advisory.load(path)
  end
end
advisories_for(name) { |load| ... } click to toggle source

Enumerates over advisories for the given gem.

@param [String] name

The gem name to lookup.

@yield [advisory]

If a block is given, each advisory for the given gem will be yielded.

@yieldparam [Advisory] advisory

An advisory for the given gem.

@return [Enumerator]

If no block is given, an Enumerator will be returned.
# File lib/bundler/audit/database.rb, line 288
def advisories_for(name)
  return enum_for(__method__,name) unless block_given?

  each_advisory_path_for(name) do |path|
    yield Advisory.load(path)
  end
end
check_gem(gem) { |advisory| ... } click to toggle source

Verifies whether the gem is effected by any advisories.

@param [Gem::Specification] gem

The gem to verify.

@yield [advisory]

If a block is given, it will be passed advisories that effect
the gem.

@yieldparam [Advisory] advisory

An advisory that effects the specific version of the gem.

@return [Enumerator]

If no block is given, an Enumerator will be returned.
# File lib/bundler/audit/database.rb, line 312
def check_gem(gem)
  return enum_for(__method__,gem) unless block_given?

  advisories_for(gem.name) do |advisory|
    if advisory.vulnerable?(gem.version)
      yield advisory
    end
  end
end
commit_id() click to toggle source

The last commit ID of the repository.

@return [String, nil]

The commit hash or `nil` if the database is not a git repository.

@since 0.9.0

# File lib/bundler/audit/database.rb, line 228
def commit_id
  if git?
    Dir.chdir(@path) do
      `git rev-parse HEAD`.chomp
    end
  end
end
git?() click to toggle source

Determines if the database is a git repository.

@return [Boolean]

@since 0.8.0

# File lib/bundler/audit/database.rb, line 180
def git?
  File.directory?(File.join(@path,'.git'))
end
inspect() click to toggle source

Inspects the database.

@return [String]

The inspected database.
# File lib/bundler/audit/database.rb, line 348
def inspect
  "#<#{self.class}:#{self}>"
end
last_updated_at() click to toggle source

Determines the time when the database was last updated.

@return [Time]

@since 0.8.0

# File lib/bundler/audit/database.rb, line 243
def last_updated_at
  if git?
    Dir.chdir(@path) do
      Time.parse(`git log --date=iso8601 --pretty="%cd" -1`)
    end
  else
    File.mtime(@path)
  end
end
size() click to toggle source

The number of advisories within the database.

@return [Integer]

The number of advisories.
# File lib/bundler/audit/database.rb, line 328
def size
  each_advisory_path.count
end
to_s() click to toggle source

Converts the database to a String.

@return [String]

The path to the database.
# File lib/bundler/audit/database.rb, line 338
def to_s
  @path
end
update!(options={}) click to toggle source

Updates the ruby-advisory-db.

@param [Hash] options

Additional options.

@option options [Boolean] :quiet

Specify whether `git` should be `--quiet`.

@return [true, nil]

* `true` - the ruby-advisory-db git repository was successfully
  updated.
* `nil` - the ruby-advisory-db is not a git repository or the `git`
  command is not installed.

@raise [UpdateFailed]

Could not update the ruby-advisory-db git repository.

@since 0.8.0

# File lib/bundler/audit/database.rb, line 204
def update!(options={})
  if git?
    Dir.chdir(@path) do
      command = %w[git pull]
      command << '--quiet' if options[:quiet]
      command << 'origin' << 'master'

      unless system(*command)
        raise(UpdateFailed,"failed to update #{@path.inspect}")
      end

      return true
    end
  end
end

Protected Instance Methods

each_advisory_path(&block) click to toggle source

Enumerates over every advisory path in the database.

@yield [path]

The given block will be passed each advisory path.

@yieldparam [String] path

A path to an advisory `.yml` file.
# File lib/bundler/audit/database.rb, line 363
def each_advisory_path(&block)
  Dir.glob(File.join(@path,'gems','*','*.yml'),&block)
end
each_advisory_path_for(name,&block) click to toggle source

Enumerates over the advisories for the given gem.

@param [String] name

The gem of the gem.

@yield [path]

The given block will be passed each advisory path.

@yieldparam [String] path

A path to an advisory `.yml` file.
# File lib/bundler/audit/database.rb, line 379
def each_advisory_path_for(name,&block)
  Dir.glob(File.join(@path,'gems',name,'*.yml'),&block)
end