summaryrefslogtreecommitdiff
path: root/vendor/gems/bundler-checksum/lib/bundler_checksum
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gems/bundler-checksum/lib/bundler_checksum')
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler_checksum/command.rb27
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler_checksum/command/helper.rb28
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler_checksum/command/init.rb83
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler_checksum/command/verify.rb52
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler_checksum/version.rb6
5 files changed, 196 insertions, 0 deletions
diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/command.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/command.rb
new file mode 100644
index 00000000000..c6c71431538
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/command.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module BundlerChecksum
+ module Command
+ autoload :Init, File.expand_path("command/init", __dir__)
+ autoload :Verify, File.expand_path("command/verify", __dir__)
+ autoload :Helper, File.expand_path("command/helper", __dir__)
+
+ def self.execute(args)
+ if args.empty?
+ $stderr.puts 'A command must be given [init,update,verify]'
+ end
+
+ if args.first == 'init'
+ Init.execute
+ elsif args.first == 'update'
+ $stderr.puts 'Not implemented, please use init'
+ elsif args.first == 'verify'
+ verified = Verify.execute
+
+ unless verified
+ exit 1
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/command/helper.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/helper.rb
new file mode 100644
index 00000000000..515f5926106
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/helper.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'json'
+require 'net/http'
+
+module BundlerChecksum::Command
+ module Helper
+ extend self
+
+ def remote_checksums_for_gem(gem_name, gem_version)
+ response = Net::HTTP.get_response(URI(
+ "https://rubygems.org/api/v1/versions/#{gem_name}.json"
+ ))
+
+ return [] unless response.code == '200'
+
+ gem_candidates = JSON.parse(response.body, symbolize_names: true)
+ gem_candidates.select! { |g| g[:number] == gem_version.to_s }
+
+ gem_candidates.map {
+ |g| {:name => gem_name, :version => gem_version, :platform => g[:platform], :checksum => g[:sha]}
+ }
+
+ rescue JSON::ParserError
+ []
+ end
+ end
+end
diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/command/init.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/init.rb
new file mode 100644
index 00000000000..1d8db7d78fa
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/init.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'openssl'
+
+module BundlerChecksum::Command
+ module Init
+ extend self
+
+ def execute
+ $stderr.puts "Initializing checksum file #{checksum_file}"
+
+ checksums = []
+
+ compact_index_cache = Bundler::Fetcher::CompactIndex
+ .new(nil, Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")), nil)
+ .send(:compact_index_client)
+ .instance_variable_get(:@cache)
+
+ Bundler.definition.resolve.sort_by(&:name).each do |spec|
+ next unless spec.source.is_a?(Bundler::Source::Rubygems)
+ spec_identifier = "#{spec.name}==#{spec.version}"
+
+ previous_checksum = previous_checksums.select do |checksum|
+ checksum[:name] == spec.name && checksum[:version] == spec.version.to_s
+ end
+
+ if !previous_checksum.empty?
+ $stderr.puts "Using #{spec_identifier}"
+ checksums += previous_checksum
+
+ next
+ end
+
+ $stderr.puts "Adding #{spec_identifier}"
+
+ compact_index_dependencies = compact_index_cache.dependencies(spec.name).select { |item| item.first == spec.version.to_s }
+
+ if !compact_index_dependencies.empty?
+ compact_index_checksums = compact_index_dependencies.map do |version, platform, dependencies, requirements|
+ {
+ name: spec.name,
+ version: spec.version.to_s,
+ platform: Gem::Platform.new(platform).to_s,
+ checksum: requirements.detect { |requirement| requirement.first == 'checksum' }.flatten[1]
+ }
+ end
+
+ checksums += compact_index_checksums.sort_by { |hash| hash.values }
+ else
+ remote_checksum = Helper.remote_checksums_for_gem(spec.name, spec.version)
+
+ if remote_checksum.empty?
+ raise "#{spec.name} #{spec.version} not found on Rubygems!"
+ end
+
+ checksums += remote_checksum.sort_by { |hash| hash.values }
+ end
+ end
+
+ File.write(checksum_file, JSON.generate(checksums, array_nl: "\n") + "\n")
+ end
+
+ private
+
+ def previous_checksums
+ @previous_checksums ||=
+ if File.exist?(checksum_file)
+ ::BundlerChecksum.checksums_from_file
+ else
+ []
+ end
+ end
+
+ def checksum_file
+ ::BundlerChecksum.checksum_file
+ end
+
+ def lockfile
+ lockfile_path = Bundler.default_lockfile
+ lockfile = Bundler::LockfileParser.new(Bundler.read_file(lockfile_path))
+ end
+ end
+end
diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/command/verify.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/verify.rb
new file mode 100644
index 00000000000..e6a52ded42c
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/verify.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module BundlerChecksum::Command
+ module Verify
+ extend self
+
+ def execute
+ $stderr.puts 'Verifying bundle checksums'
+
+ verified = true
+
+ local_checksums.each do |gem|
+ name = gem.fetch(:name)
+ version = gem.fetch(:version)
+ platform = gem.fetch(:platform)
+ checksum = gem.fetch(:checksum)
+
+ $stderr.puts "Verifying #{name}==#{version} #{platform}"
+ unless validate_gem_checksum(name, version, platform, checksum)
+ verified = false
+ end
+ end
+
+ verified
+ end
+
+ private
+
+ def local_checksums
+ ::BundlerChecksum.checksums_from_file
+ end
+
+ def validate_gem_checksum(gem_name, gem_version, gem_platform, local_checksum)
+ remote_checksums = Helper.remote_checksums_for_gem(gem_name, gem_version)
+ if remote_checksums.empty?
+ $stderr.puts "#{gem_name} #{gem_version} not found on Rubygems, skipping"
+ return false
+ end
+
+ remote_platform_checksum = remote_checksums.find { |g| g[:name] == gem_name && g[:platform] == gem_platform.to_s }
+
+ if local_checksum == remote_platform_checksum[:checksum]
+ true
+ else
+ $stderr.puts "Gem #{gem_name} #{gem_version} #{gem_platform} failed checksum verification"
+ $stderr.puts "LOCAL: #{local_checksum}"
+ $stderr.puts "REMOTE: #{remote_platform_checksum[:checksum]}"
+ return false
+ end
+ end
+ end
+end
diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/version.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/version.rb
new file mode 100644
index 00000000000..367a9e49a47
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/version.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+module BundlerChecksum
+ # bundler-checksum version
+ VERSION = '0.1.0'
+end