Skip to content

Commit

Permalink
bundler: avoid repeat lockfile parsing with caching (dependabot#9443)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakecoffman authored Apr 5, 2024
1 parent 4ff4257 commit d7e6972
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 8 deletions.
24 changes: 24 additions & 0 deletions bundler/lib/dependabot/bundler/cached_lockfile_parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# typed: strong
# frozen_string_literal: true

require "sorbet-runtime"
require "digest"
require "digest/sha2"
require "bundler/lockfile_parser"

module Dependabot
module Bundler
class CachedLockfileParser
extend T::Sig

sig { params(lockfile_content: String).returns(::Bundler::LockfileParser) }
def self.parse(lockfile_content)
lockfile_hash = Digest::SHA2.hexdigest(lockfile_content)
@cache ||= T.let({}, T.nilable(T::Hash[String, ::Bundler::LockfileParser]))
return T.must(@cache[lockfile_hash]) if @cache.key?(lockfile_hash)

@cache[lockfile_hash] = ::Bundler::LockfileParser.new(lockfile_content)
end
end
end
end
4 changes: 2 additions & 2 deletions bundler/lib/dependabot/bundler/file_fetcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require "dependabot/file_fetchers"
require "dependabot/file_fetchers/base"
require "dependabot/bundler/file_updater/lockfile_updater"
require "dependabot/bundler/cached_lockfile_parser"
require "dependabot/errors"

module Dependabot
Expand Down Expand Up @@ -162,8 +163,7 @@ def fetch_gemspecs_from_directory(dir_path)

def fetch_path_gemspec_paths
if lockfile
parsed_lockfile = ::Bundler::LockfileParser
.new(sanitized_lockfile_content)
parsed_lockfile = CachedLockfileParser.parse(sanitized_lockfile_content)
parsed_lockfile.specs
.select { |s| s.source.instance_of?(::Bundler::Source::Path) }
.map { |s| s.source.path }.uniq
Expand Down
4 changes: 2 additions & 2 deletions bundler/lib/dependabot/bundler/file_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require "dependabot/bundler/native_helpers"
require "dependabot/bundler/helpers"
require "dependabot/bundler/version"
require "dependabot/bundler/cached_lockfile_parser"
require "dependabot/shared_helpers"
require "dependabot/errors"

Expand Down Expand Up @@ -255,8 +256,7 @@ def lockfile
end

def parsed_lockfile
@parsed_lockfile ||=
::Bundler::LockfileParser.new(sanitized_lockfile_content)
@parsed_lockfile ||= CachedLockfileParser.parse(sanitized_lockfile_content)
end

def production_dep_names
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require "dependabot/shared_helpers"
require "dependabot/errors"
require "dependabot/bundler/file_updater"
require "dependabot/bundler/cached_lockfile_parser"
require "dependabot/bundler/native_helpers"
require "dependabot/bundler/helpers"

Expand Down Expand Up @@ -216,8 +217,8 @@ def replacement_version_for_gemspec(path, gemspec_content)
.dependency_name || File.basename(path, ".gemspec")

gemspec_specs =
::Bundler::LockfileParser.new(sanitized_lockfile_body).specs
.select { |s| s.name == gem_name && gemspec_sources.include?(s.source.class) }
CachedLockfileParser.parse(sanitized_lockfile_body).specs
.select { |s| s.name == gem_name && gemspec_sources.include?(s.source.class) }

gemspec_specs.first&.version || "0.0.1"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

require "dependabot/dependency_file"
require "dependabot/bundler/update_checker"
require "dependabot/bundler/cached_lockfile_parser"
require "dependabot/bundler/file_updater/gemspec_sanitizer"
require "dependabot/bundler/file_updater/git_pin_replacer"
require "dependabot/bundler/file_updater/git_source_remover"
Expand Down Expand Up @@ -268,8 +269,8 @@ def replacement_version_for_gemspec(gemspec_content)
return "0.0.1" unless lockfile

gemspec_specs =
::Bundler::LockfileParser.new(sanitized_lockfile_content).specs
.select { |s| gemspec_sources.include?(s.source.class) }
CachedLockfileParser.parse(sanitized_lockfile_content).specs
.select { |s| gemspec_sources.include?(s.source.class) }

gem_name =
FileUpdater::GemspecDependencyNameFinder
Expand Down

0 comments on commit d7e6972

Please sign in to comment.