parent
2581de112c
commit
49b0f3b024
Notes:
git
2022-12-15 10:07:00 +00:00
@ -61,9 +61,6 @@ module Bundler
|
|||||||
req.basic_auth(user, password)
|
req.basic_auth(user, password)
|
||||||
end
|
end
|
||||||
connection.request(uri, req)
|
connection.request(uri, req)
|
||||||
rescue NoMethodError => e
|
|
||||||
raise unless ["undefined method", "use_ssl="].all? {|snippet| e.message.include? snippet }
|
|
||||||
raise LoadError.new("cannot load such file -- openssl")
|
|
||||||
rescue OpenSSL::SSL::SSLError
|
rescue OpenSSL::SSL::SSLError
|
||||||
raise CertificateFailureError.new(uri)
|
raise CertificateFailureError.new(uri)
|
||||||
rescue *HTTP_ERRORS => e
|
rescue *HTTP_ERRORS => e
|
||||||
|
@ -36,9 +36,6 @@ module Bundler
|
|||||||
end
|
end
|
||||||
when Thor::Error
|
when Thor::Error
|
||||||
Bundler.ui.error error.message
|
Bundler.ui.error error.message
|
||||||
when LoadError
|
|
||||||
raise error unless /cannot load such file -- openssl|openssl.so|libcrypto.so/.match?(error.message)
|
|
||||||
Bundler.ui.error "\nCould not load OpenSSL. #{error.class}: #{error}\n#{error.backtrace.join("\n ")}"
|
|
||||||
when Interrupt
|
when Interrupt
|
||||||
Bundler.ui.error "\nQuitting..."
|
Bundler.ui.error "\nQuitting..."
|
||||||
Bundler.ui.trace error
|
Bundler.ui.trace error
|
||||||
|
@ -148,7 +148,7 @@ module Bundler
|
|||||||
"#{current_branch} but Gemfile specifies #{branch}"
|
"#{current_branch} but Gemfile specifies #{branch}"
|
||||||
end
|
end
|
||||||
|
|
||||||
changed = cached_revision && cached_revision != git_proxy.revision
|
changed = cached_revision && cached_revision != revision
|
||||||
|
|
||||||
if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(cached_revision)
|
if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(cached_revision)
|
||||||
raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \
|
raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \
|
||||||
|
@ -61,7 +61,7 @@ module Bundler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def revision
|
def revision
|
||||||
@revision ||= find_local_revision
|
@revision ||= allowed_with_path { find_local_revision }
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_branch
|
def current_branch
|
||||||
@ -90,16 +90,11 @@ module Bundler
|
|||||||
|
|
||||||
Bundler.ui.info "Fetching #{credential_filtered_uri}"
|
Bundler.ui.info "Fetching #{credential_filtered_uri}"
|
||||||
|
|
||||||
unless path.exist?
|
extra_fetch_needed = clone_needs_extra_fetch?
|
||||||
SharedHelpers.filesystem_access(path.dirname) do |p|
|
unshallow_needed = clone_needs_unshallow?
|
||||||
FileUtils.mkdir_p(p)
|
return unless extra_fetch_needed || unshallow_needed
|
||||||
end
|
|
||||||
git_retry "clone", "--bare", "--no-hardlinks", "--quiet", *extra_clone_args, "--", configured_uri, path.to_s
|
|
||||||
return unless extra_ref
|
|
||||||
end
|
|
||||||
|
|
||||||
fetch_args = extra_fetch_args
|
fetch_args = unshallow_needed ? ["--unshallow"] : depth_args
|
||||||
fetch_args.unshift("--unshallow") if path.join("shallow").exist? && full_clone?
|
|
||||||
|
|
||||||
git_retry(*["fetch", "--force", "--quiet", "--no-tags", *fetch_args, "--", configured_uri, refspec].compact, :dir => path)
|
git_retry(*["fetch", "--force", "--quiet", "--no-tags", *fetch_args, "--", configured_uri, refspec].compact, :dir => path)
|
||||||
end
|
end
|
||||||
@ -123,7 +118,7 @@ module Bundler
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
git(*["fetch", "--force", "--quiet", *extra_fetch_args, path.to_s, revision_refspec].compact, :dir => destination)
|
git "fetch", "--force", "--quiet", *extra_fetch_args, :dir => destination
|
||||||
|
|
||||||
git "reset", "--hard", @revision, :dir => destination
|
git "reset", "--hard", @revision, :dir => destination
|
||||||
|
|
||||||
@ -137,6 +132,24 @@ module Bundler
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def clone_needs_extra_fetch?
|
||||||
|
return true if path.exist?
|
||||||
|
|
||||||
|
SharedHelpers.filesystem_access(path.dirname) do |p|
|
||||||
|
FileUtils.mkdir_p(p)
|
||||||
|
end
|
||||||
|
git_retry "clone", "--bare", "--no-hardlinks", "--quiet", *extra_clone_args, "--", configured_uri, path.to_s
|
||||||
|
|
||||||
|
extra_ref
|
||||||
|
end
|
||||||
|
|
||||||
|
def clone_needs_unshallow?
|
||||||
|
return false unless path.join("shallow").exist?
|
||||||
|
return true if full_clone?
|
||||||
|
|
||||||
|
@revision && @revision != head_revision
|
||||||
|
end
|
||||||
|
|
||||||
def extra_ref
|
def extra_ref
|
||||||
return false if not_pinned?
|
return false if not_pinned?
|
||||||
return true unless full_clone?
|
return true unless full_clone?
|
||||||
@ -147,7 +160,7 @@ module Bundler
|
|||||||
def depth
|
def depth
|
||||||
return @depth if defined?(@depth)
|
return @depth if defined?(@depth)
|
||||||
|
|
||||||
@depth = if legacy_locked_revision? || !supports_fetching_unreachable_refs?
|
@depth = if !supports_fetching_unreachable_refs?
|
||||||
nil
|
nil
|
||||||
elsif not_pinned?
|
elsif not_pinned?
|
||||||
1
|
1
|
||||||
@ -241,11 +254,24 @@ module Bundler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_local_revision
|
def find_local_revision
|
||||||
allowed_with_path do
|
options_ref = branch || tag || ref
|
||||||
git("rev-parse", "--verify", branch || tag || ref || "HEAD", :dir => path).strip
|
return head_revision if options_ref.nil?
|
||||||
end
|
|
||||||
|
find_revision_for(options_ref)
|
||||||
|
end
|
||||||
|
|
||||||
|
def head_revision
|
||||||
|
verify("HEAD")
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_revision_for(reference)
|
||||||
|
verify(reference)
|
||||||
rescue GitCommandError => e
|
rescue GitCommandError => e
|
||||||
raise MissingGitRevisionError.new(e.command, path, branch || tag || ref, credential_filtered_uri)
|
raise MissingGitRevisionError.new(e.command, path, reference, credential_filtered_uri)
|
||||||
|
end
|
||||||
|
|
||||||
|
def verify(reference)
|
||||||
|
git("rev-parse", "--verify", reference, :dir => path).strip
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds credentials to the URI
|
# Adds credentials to the URI
|
||||||
@ -325,16 +351,16 @@ module Bundler
|
|||||||
args
|
args
|
||||||
end
|
end
|
||||||
|
|
||||||
def extra_fetch_args
|
def depth_args
|
||||||
return [] if full_clone?
|
return [] if full_clone?
|
||||||
|
|
||||||
["--depth", depth.to_s]
|
["--depth", depth.to_s]
|
||||||
end
|
end
|
||||||
|
|
||||||
def revision_refspec
|
def extra_fetch_args
|
||||||
return if legacy_locked_revision?
|
extra_args = [path.to_s, *depth_args]
|
||||||
|
extra_args.push(revision) unless legacy_locked_revision?
|
||||||
revision
|
extra_args
|
||||||
end
|
end
|
||||||
|
|
||||||
def full_clone?
|
def full_clone?
|
||||||
|
@ -178,26 +178,6 @@ RSpec.describe Bundler::Fetcher::Downloader do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the request response causes a NoMethodError" do
|
|
||||||
before { allow(connection).to receive(:request).with(uri, net_http_get) { raise NoMethodError.new(message) } }
|
|
||||||
|
|
||||||
context "and the error message is about use_ssl=" do
|
|
||||||
let(:message) { "undefined method 'use_ssl='" }
|
|
||||||
|
|
||||||
it "should raise a LoadError about openssl" do
|
|
||||||
expect { subject.request(uri, options) }.to raise_error(LoadError, "cannot load such file -- openssl")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "and the error message is not about use_ssl=" do
|
|
||||||
let(:message) { "undefined method 'undefined_method_call'" }
|
|
||||||
|
|
||||||
it "should raise the original NoMethodError" do
|
|
||||||
expect { subject.request(uri, options) }.to raise_error(NoMethodError, /undefined method 'undefined_method_call'/)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when the request response causes a OpenSSL::SSL::SSLError" do
|
context "when the request response causes a OpenSSL::SSL::SSLError" do
|
||||||
before { allow(connection).to receive(:request).with(uri, net_http_get) { raise OpenSSL::SSL::SSLError.new } }
|
before { allow(connection).to receive(:request).with(uri, net_http_get) { raise OpenSSL::SSL::SSLError.new } }
|
||||||
|
|
||||||
|
@ -110,19 +110,6 @@ RSpec.describe Bundler, "friendly errors" do
|
|||||||
it_behaves_like "Bundler.ui receive error", Bundler::Thor::Error.new
|
it_behaves_like "Bundler.ui receive error", Bundler::Thor::Error.new
|
||||||
end
|
end
|
||||||
|
|
||||||
context "LoadError" do
|
|
||||||
let(:error) { LoadError.new("cannot load such file -- openssl") }
|
|
||||||
|
|
||||||
before do
|
|
||||||
allow(error).to receive(:backtrace).and_return(["backtrace"])
|
|
||||||
end
|
|
||||||
|
|
||||||
it "Bundler.ui receive error" do
|
|
||||||
expect(Bundler.ui).to receive(:error).with("\nCould not load OpenSSL. LoadError: cannot load such file -- openssl\nbacktrace")
|
|
||||||
Bundler::FriendlyErrors.log_error(error)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "Interrupt" do
|
context "Interrupt" do
|
||||||
it "Bundler.ui receive error" do
|
it "Bundler.ui receive error" do
|
||||||
expect(Bundler.ui).to receive(:error).with("\nQuitting...")
|
expect(Bundler.ui).to receive(:error).with("\nQuitting...")
|
||||||
|
@ -34,6 +34,13 @@ RSpec.describe "bundle lock with git gems" do
|
|||||||
expect(out).to eq("WIN")
|
expect(out).to eq("WIN")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "properly clones a git source locked to an out of date ref" do
|
||||||
|
update_git "foo"
|
||||||
|
|
||||||
|
bundle :install, :env => { "BUNDLE_PATH" => "foo" }
|
||||||
|
expect(err).to be_empty
|
||||||
|
end
|
||||||
|
|
||||||
it "provides correct #full_gem_path" do
|
it "provides correct #full_gem_path" do
|
||||||
run <<-RUBY
|
run <<-RUBY
|
||||||
puts Bundler.rubygems.find_name('foo').first.full_gem_path
|
puts Bundler.rubygems.find_name('foo').first.full_gem_path
|
||||||
|
@ -1,120 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/compact_index"
|
||||||
|
require_relative "helpers/artifice"
|
||||||
$LOAD_PATH.unshift Dir[Spec::Path.base_system_gem_path.join("gems/compact_index*/lib")].first.to_s
|
|
||||||
require "compact_index"
|
|
||||||
|
|
||||||
class CompactIndexAPI < Endpoint
|
|
||||||
helpers do
|
|
||||||
include Spec::Path
|
|
||||||
|
|
||||||
def load_spec(name, version, platform, gem_repo)
|
|
||||||
full_name = "#{name}-#{version}"
|
|
||||||
full_name += "-#{platform}" if platform != "ruby"
|
|
||||||
Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
|
|
||||||
end
|
|
||||||
|
|
||||||
def etag_response
|
|
||||||
response_body = yield
|
|
||||||
checksum = Digest(:MD5).hexdigest(response_body)
|
|
||||||
return if not_modified?(checksum)
|
|
||||||
headers "ETag" => quote(checksum)
|
|
||||||
headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
|
|
||||||
content_type "text/plain"
|
|
||||||
requested_range_for(response_body)
|
|
||||||
rescue StandardError => e
|
|
||||||
puts e
|
|
||||||
puts e.backtrace
|
|
||||||
raise
|
|
||||||
end
|
|
||||||
|
|
||||||
def not_modified?(checksum)
|
|
||||||
etags = parse_etags(request.env["HTTP_IF_NONE_MATCH"])
|
|
||||||
|
|
||||||
return unless etags.include?(checksum)
|
|
||||||
headers "ETag" => quote(checksum)
|
|
||||||
status 304
|
|
||||||
body ""
|
|
||||||
end
|
|
||||||
|
|
||||||
def requested_range_for(response_body)
|
|
||||||
ranges = Rack::Utils.byte_ranges(env, response_body.bytesize)
|
|
||||||
|
|
||||||
if ranges
|
|
||||||
status 206
|
|
||||||
body ranges.map! {|range| slice_body(response_body, range) }.join
|
|
||||||
else
|
|
||||||
status 200
|
|
||||||
body response_body
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def quote(string)
|
|
||||||
%("#{string}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_etags(value)
|
|
||||||
value ? value.split(/, ?/).select {|s| s.sub!(/"(.*)"/, '\1') } : []
|
|
||||||
end
|
|
||||||
|
|
||||||
def slice_body(body, range)
|
|
||||||
body.byteslice(range)
|
|
||||||
end
|
|
||||||
|
|
||||||
def gems(gem_repo = default_gem_repo)
|
|
||||||
@gems ||= {}
|
|
||||||
@gems[gem_repo] ||= begin
|
|
||||||
specs = Bundler::Deprecate.skip_during do
|
|
||||||
%w[specs.4.8 prerelease_specs.4.8].map do |filename|
|
|
||||||
Marshal.load(File.open(gem_repo.join(filename)).read).map do |name, version, platform|
|
|
||||||
load_spec(name, version, platform, gem_repo)
|
|
||||||
end
|
|
||||||
end.flatten
|
|
||||||
end
|
|
||||||
|
|
||||||
specs.group_by(&:name).map do |name, versions|
|
|
||||||
gem_versions = versions.map do |spec|
|
|
||||||
deps = spec.dependencies.select {|d| d.type == :runtime }.map do |d|
|
|
||||||
reqs = d.requirement.requirements.map {|r| r.join(" ") }.join(", ")
|
|
||||||
CompactIndex::Dependency.new(d.name, reqs)
|
|
||||||
end
|
|
||||||
checksum = begin
|
|
||||||
Digest(:SHA256).file("#{gem_repo}/gems/#{spec.original_name}.gem").base64digest
|
|
||||||
rescue StandardError
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
CompactIndex::GemVersion.new(spec.version.version, spec.platform.to_s, checksum, nil,
|
|
||||||
deps, spec.required_ruby_version.to_s, spec.required_rubygems_version.to_s)
|
|
||||||
end
|
|
||||||
CompactIndex::Gem.new(name, gem_versions)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/names" do
|
|
||||||
etag_response do
|
|
||||||
CompactIndex.names(gems.map(&:name))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/versions" do
|
|
||||||
etag_response do
|
|
||||||
file = tmp("versions.list")
|
|
||||||
FileUtils.rm_f(file)
|
|
||||||
file = CompactIndex::VersionsFile.new(file.to_s)
|
|
||||||
file.create(gems)
|
|
||||||
file.contents
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/info/:name" do
|
|
||||||
etag_response do
|
|
||||||
gem = gems.find {|g| g.name == params[:name] }
|
|
||||||
CompactIndex.info(gem ? gem.versions : [])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexAPI)
|
Artifice.activate_with(CompactIndexAPI)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexApiMissing < CompactIndexAPI
|
class CompactIndexApiMissing < CompactIndexAPI
|
||||||
get "/fetch/actual/gem/:id" do
|
get "/fetch/actual/gem/:id" do
|
||||||
@ -10,4 +8,6 @@ class CompactIndexApiMissing < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexApiMissing)
|
Artifice.activate_with(CompactIndexApiMissing)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexBasicAuthentication < CompactIndexAPI
|
class CompactIndexBasicAuthentication < CompactIndexAPI
|
||||||
before do
|
before do
|
||||||
@ -12,4 +10,6 @@ class CompactIndexBasicAuthentication < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexBasicAuthentication)
|
Artifice.activate_with(CompactIndexBasicAuthentication)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexChecksumMismatch < CompactIndexAPI
|
class CompactIndexChecksumMismatch < CompactIndexAPI
|
||||||
get "/versions" do
|
get "/versions" do
|
||||||
@ -13,4 +11,6 @@ class CompactIndexChecksumMismatch < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexChecksumMismatch)
|
Artifice.activate_with(CompactIndexChecksumMismatch)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexConcurrentDownload < CompactIndexAPI
|
class CompactIndexConcurrentDownload < CompactIndexAPI
|
||||||
get "/versions" do
|
get "/versions" do
|
||||||
@ -29,4 +27,6 @@ class CompactIndexConcurrentDownload < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexConcurrentDownload)
|
Artifice.activate_with(CompactIndexConcurrentDownload)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexCredsDiffHost < CompactIndexAPI
|
class CompactIndexCredsDiffHost < CompactIndexAPI
|
||||||
helpers do
|
helpers do
|
||||||
@ -36,4 +34,6 @@ class CompactIndexCredsDiffHost < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexCredsDiffHost)
|
Artifice.activate_with(CompactIndexCredsDiffHost)
|
||||||
|
@ -1,37 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index_extra"
|
||||||
|
require_relative "helpers/artifice"
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexExtra < CompactIndexAPI
|
|
||||||
get "/extra/versions" do
|
|
||||||
halt 404
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/api/v1/dependencies" do
|
|
||||||
halt 404
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/specs.4.8.gz" do
|
|
||||||
File.binread("#{gem_repo2}/specs.4.8.gz")
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/prerelease_specs.4.8.gz" do
|
|
||||||
File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/quick/Marshal.4.8/:id" do
|
|
||||||
redirect "/extra/fetch/actual/gem/#{params[:id]}"
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/fetch/actual/gem/:id" do
|
|
||||||
File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/gems/:id" do
|
|
||||||
File.binread("#{gem_repo2}/gems/#{params[:id]}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexExtra)
|
Artifice.activate_with(CompactIndexExtra)
|
||||||
|
@ -1,52 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index_extra_api"
|
||||||
|
require_relative "helpers/artifice"
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexExtraApi < CompactIndexAPI
|
|
||||||
get "/extra/names" do
|
|
||||||
etag_response do
|
|
||||||
CompactIndex.names(gems(gem_repo4).map(&:name))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/versions" do
|
|
||||||
etag_response do
|
|
||||||
file = tmp("versions.list")
|
|
||||||
FileUtils.rm_f(file)
|
|
||||||
file = CompactIndex::VersionsFile.new(file.to_s)
|
|
||||||
file.create(gems(gem_repo4))
|
|
||||||
file.contents
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/info/:name" do
|
|
||||||
etag_response do
|
|
||||||
gem = gems(gem_repo4).find {|g| g.name == params[:name] }
|
|
||||||
CompactIndex.info(gem ? gem.versions : [])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/specs.4.8.gz" do
|
|
||||||
File.binread("#{gem_repo4}/specs.4.8.gz")
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/prerelease_specs.4.8.gz" do
|
|
||||||
File.binread("#{gem_repo4}/prerelease_specs.4.8.gz")
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/quick/Marshal.4.8/:id" do
|
|
||||||
redirect "/extra/fetch/actual/gem/#{params[:id]}"
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/fetch/actual/gem/:id" do
|
|
||||||
File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/extra/gems/:id" do
|
|
||||||
File.binread("#{gem_repo4}/gems/#{params[:id]}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexExtraApi)
|
Artifice.activate_with(CompactIndexExtraApi)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index_extra_api"
|
require_relative "helpers/compact_index_extra_api"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexExtraAPIMissing < CompactIndexExtraApi
|
class CompactIndexExtraAPIMissing < CompactIndexExtraApi
|
||||||
get "/extra/fetch/actual/gem/:id" do
|
get "/extra/fetch/actual/gem/:id" do
|
||||||
@ -14,4 +12,6 @@ class CompactIndexExtraAPIMissing < CompactIndexExtraApi
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexExtraAPIMissing)
|
Artifice.activate_with(CompactIndexExtraAPIMissing)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index_extra"
|
require_relative "helpers/compact_index_extra"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexExtraMissing < CompactIndexExtra
|
class CompactIndexExtraMissing < CompactIndexExtra
|
||||||
get "/extra/fetch/actual/gem/:id" do
|
get "/extra/fetch/actual/gem/:id" do
|
||||||
@ -14,4 +12,6 @@ class CompactIndexExtraMissing < CompactIndexExtra
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexExtraMissing)
|
Artifice.activate_with(CompactIndexExtraMissing)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexForbidden < CompactIndexAPI
|
class CompactIndexForbidden < CompactIndexAPI
|
||||||
get "/versions" do
|
get "/versions" do
|
||||||
@ -10,4 +8,6 @@ class CompactIndexForbidden < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexForbidden)
|
Artifice.activate_with(CompactIndexForbidden)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexHostRedirect < CompactIndexAPI
|
class CompactIndexHostRedirect < CompactIndexAPI
|
||||||
get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do
|
get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do
|
||||||
@ -18,4 +16,6 @@ class CompactIndexHostRedirect < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexHostRedirect)
|
Artifice.activate_with(CompactIndexHostRedirect)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexNoGem < CompactIndexAPI
|
class CompactIndexNoGem < CompactIndexAPI
|
||||||
get "/gems/:id" do
|
get "/gems/:id" do
|
||||||
@ -10,4 +8,6 @@ class CompactIndexNoGem < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexNoGem)
|
Artifice.activate_with(CompactIndexNoGem)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexPartialUpdate < CompactIndexAPI
|
class CompactIndexPartialUpdate < CompactIndexAPI
|
||||||
# Stub the server to never return 304s. This simulates the behaviour of
|
# Stub the server to never return 304s. This simulates the behaviour of
|
||||||
@ -35,4 +33,6 @@ class CompactIndexPartialUpdate < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexPartialUpdate)
|
Artifice.activate_with(CompactIndexPartialUpdate)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexPartialUpdateNoEtagNotIncremental < CompactIndexAPI
|
class CompactIndexPartialUpdateNoEtagNotIncremental < CompactIndexAPI
|
||||||
def partial_update_no_etag
|
def partial_update_no_etag
|
||||||
@ -37,4 +35,6 @@ class CompactIndexPartialUpdateNoEtagNotIncremental < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexPartialUpdateNoEtagNotIncremental)
|
Artifice.activate_with(CompactIndexPartialUpdateNoEtagNotIncremental)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexPrecompiledBefore < CompactIndexAPI
|
class CompactIndexPrecompiledBefore < CompactIndexAPI
|
||||||
get "/info/:name" do
|
get "/info/:name" do
|
||||||
@ -22,4 +20,6 @@ class CompactIndexPrecompiledBefore < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexPrecompiledBefore)
|
Artifice.activate_with(CompactIndexPrecompiledBefore)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexRangeNotSatisfiable < CompactIndexAPI
|
class CompactIndexRangeNotSatisfiable < CompactIndexAPI
|
||||||
get "/versions" do
|
get "/versions" do
|
||||||
@ -31,4 +29,6 @@ class CompactIndexRangeNotSatisfiable < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexRangeNotSatisfiable)
|
Artifice.activate_with(CompactIndexRangeNotSatisfiable)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexRateLimited < CompactIndexAPI
|
class CompactIndexRateLimited < CompactIndexAPI
|
||||||
class RequestCounter
|
class RequestCounter
|
||||||
@ -45,4 +43,6 @@ class CompactIndexRateLimited < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexRateLimited)
|
Artifice.activate_with(CompactIndexRateLimited)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexRedirect < CompactIndexAPI
|
class CompactIndexRedirect < CompactIndexAPI
|
||||||
get "/fetch/actual/gem/:id" do
|
get "/fetch/actual/gem/:id" do
|
||||||
@ -18,4 +16,6 @@ class CompactIndexRedirect < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexRedirect)
|
Artifice.activate_with(CompactIndexRedirect)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexStrictBasicAuthentication < CompactIndexAPI
|
class CompactIndexStrictBasicAuthentication < CompactIndexAPI
|
||||||
before do
|
before do
|
||||||
@ -17,4 +15,6 @@ class CompactIndexStrictBasicAuthentication < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexStrictBasicAuthentication)
|
Artifice.activate_with(CompactIndexStrictBasicAuthentication)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexWrongDependencies < CompactIndexAPI
|
class CompactIndexWrongDependencies < CompactIndexAPI
|
||||||
get "/info/:name" do
|
get "/info/:name" do
|
||||||
@ -14,4 +12,6 @@ class CompactIndexWrongDependencies < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexWrongDependencies)
|
Artifice.activate_with(CompactIndexWrongDependencies)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "compact_index"
|
require_relative "helpers/compact_index"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class CompactIndexWrongGemChecksum < CompactIndexAPI
|
class CompactIndexWrongGemChecksum < CompactIndexAPI
|
||||||
get "/info/:name" do
|
get "/info/:name" do
|
||||||
@ -17,4 +15,6 @@ class CompactIndexWrongGemChecksum < CompactIndexAPI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(CompactIndexWrongGemChecksum)
|
Artifice.activate_with(CompactIndexWrongGemChecksum)
|
||||||
|
@ -1,115 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "../path"
|
require_relative "helpers/endpoint"
|
||||||
|
require_relative "helpers/artifice"
|
||||||
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
|
|
||||||
|
|
||||||
require "artifice"
|
|
||||||
require "sinatra/base"
|
|
||||||
|
|
||||||
ALL_REQUESTS = [] # rubocop:disable Style/MutableConstant
|
|
||||||
ALL_REQUESTS_MUTEX = Thread::Mutex.new
|
|
||||||
|
|
||||||
at_exit do
|
|
||||||
if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"]
|
|
||||||
expected = expected.split("\n").sort
|
|
||||||
actual = ALL_REQUESTS.sort
|
|
||||||
|
|
||||||
unless expected == actual
|
|
||||||
raise "Unexpected requests!\nExpected:\n\t#{expected.join("\n\t")}\n\nActual:\n\t#{actual.join("\n\t")}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Endpoint < Sinatra::Base
|
|
||||||
def self.all_requests
|
|
||||||
@all_requests ||= []
|
|
||||||
end
|
|
||||||
|
|
||||||
set :raise_errors, true
|
|
||||||
set :show_exceptions, false
|
|
||||||
|
|
||||||
def call!(*)
|
|
||||||
super.tap do
|
|
||||||
ALL_REQUESTS_MUTEX.synchronize do
|
|
||||||
ALL_REQUESTS << @request.url
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers do
|
|
||||||
include Spec::Path
|
|
||||||
|
|
||||||
def default_gem_repo
|
|
||||||
if ENV["BUNDLER_SPEC_GEM_REPO"]
|
|
||||||
Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"])
|
|
||||||
else
|
|
||||||
case request.host
|
|
||||||
when "gem.repo1"
|
|
||||||
Spec::Path.gem_repo1
|
|
||||||
when "gem.repo2"
|
|
||||||
Spec::Path.gem_repo2
|
|
||||||
when "gem.repo3"
|
|
||||||
Spec::Path.gem_repo3
|
|
||||||
when "gem.repo4"
|
|
||||||
Spec::Path.gem_repo4
|
|
||||||
else
|
|
||||||
Spec::Path.gem_repo1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def dependencies_for(gem_names, gem_repo = default_gem_repo)
|
|
||||||
return [] if gem_names.nil? || gem_names.empty?
|
|
||||||
|
|
||||||
all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename|
|
|
||||||
Marshal.load(File.open(gem_repo.join(filename)).read)
|
|
||||||
end.inject(:+)
|
|
||||||
|
|
||||||
all_specs.map do |name, version, platform|
|
|
||||||
spec = load_spec(name, version, platform, gem_repo)
|
|
||||||
next unless gem_names.include?(spec.name)
|
|
||||||
{
|
|
||||||
:name => spec.name,
|
|
||||||
:number => spec.version.version,
|
|
||||||
:platform => spec.platform.to_s,
|
|
||||||
:dependencies => spec.dependencies.select {|dep| dep.type == :runtime }.map do |dep|
|
|
||||||
[dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")]
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
end.compact
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_spec(name, version, platform, gem_repo)
|
|
||||||
full_name = "#{name}-#{version}"
|
|
||||||
full_name += "-#{platform}" if platform != "ruby"
|
|
||||||
Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/quick/Marshal.4.8/:id" do
|
|
||||||
redirect "/fetch/actual/gem/#{params[:id]}"
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/fetch/actual/gem/:id" do
|
|
||||||
File.binread("#{default_gem_repo}/quick/Marshal.4.8/#{params[:id]}")
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/gems/:id" do
|
|
||||||
File.binread("#{default_gem_repo}/gems/#{params[:id]}")
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/api/v1/dependencies" do
|
|
||||||
Marshal.dump(dependencies_for(params[:gems]))
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/specs.4.8.gz" do
|
|
||||||
File.binread("#{default_gem_repo}/specs.4.8.gz")
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/prerelease_specs.4.8.gz" do
|
|
||||||
File.binread("#{default_gem_repo}/prerelease_specs.4.8.gz")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Artifice.activate_with(Endpoint)
|
Artifice.activate_with(Endpoint)
|
||||||
|
@ -2,17 +2,16 @@
|
|||||||
|
|
||||||
require_relative "../path"
|
require_relative "../path"
|
||||||
|
|
||||||
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
|
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
|
||||||
|
|
||||||
require "artifice"
|
|
||||||
require "sinatra/base"
|
require "sinatra/base"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class Endpoint500 < Sinatra::Base
|
class Endpoint500 < Sinatra::Base
|
||||||
before do
|
before do
|
||||||
halt 500
|
halt 500
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(Endpoint500)
|
Artifice.activate_with(Endpoint500)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointApiForbidden < Endpoint
|
class EndpointApiForbidden < Endpoint
|
||||||
get "/api/v1/dependencies" do
|
get "/api/v1/dependencies" do
|
||||||
@ -10,4 +8,6 @@ class EndpointApiForbidden < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointApiForbidden)
|
Artifice.activate_with(EndpointApiForbidden)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointBasicAuthentication < Endpoint
|
class EndpointBasicAuthentication < Endpoint
|
||||||
before do
|
before do
|
||||||
@ -12,4 +10,6 @@ class EndpointBasicAuthentication < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointBasicAuthentication)
|
Artifice.activate_with(EndpointBasicAuthentication)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointCredsDiffHost < Endpoint
|
class EndpointCredsDiffHost < Endpoint
|
||||||
helpers do
|
helpers do
|
||||||
@ -36,4 +34,6 @@ class EndpointCredsDiffHost < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointCredsDiffHost)
|
Artifice.activate_with(EndpointCredsDiffHost)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointExtra < Endpoint
|
class EndpointExtra < Endpoint
|
||||||
get "/extra/api/v1/dependencies" do
|
get "/extra/api/v1/dependencies" do
|
||||||
@ -30,4 +28,6 @@ class EndpointExtra < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointExtra)
|
Artifice.activate_with(EndpointExtra)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointExtraApi < Endpoint
|
class EndpointExtraApi < Endpoint
|
||||||
get "/extra/api/v1/dependencies" do
|
get "/extra/api/v1/dependencies" do
|
||||||
@ -31,4 +29,6 @@ class EndpointExtraApi < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointExtraApi)
|
Artifice.activate_with(EndpointExtraApi)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint_extra"
|
require_relative "helpers/endpoint_extra"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointExtraMissing < EndpointExtra
|
class EndpointExtraMissing < EndpointExtra
|
||||||
get "/extra/fetch/actual/gem/:id" do
|
get "/extra/fetch/actual/gem/:id" do
|
||||||
@ -14,4 +12,6 @@ class EndpointExtraMissing < EndpointExtra
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointExtraMissing)
|
Artifice.activate_with(EndpointExtraMissing)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointFallback < Endpoint
|
class EndpointFallback < Endpoint
|
||||||
DEPENDENCY_LIMIT = 60
|
DEPENDENCY_LIMIT = 60
|
||||||
@ -16,4 +14,6 @@ class EndpointFallback < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointFallback)
|
Artifice.activate_with(EndpointFallback)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointHostRedirect < Endpoint
|
class EndpointHostRedirect < Endpoint
|
||||||
get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do
|
get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do
|
||||||
@ -14,4 +12,6 @@ class EndpointHostRedirect < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointHostRedirect)
|
Artifice.activate_with(EndpointHostRedirect)
|
||||||
|
@ -1,13 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint_fallback"
|
require_relative "helpers/endpoint_marshal_fail"
|
||||||
|
require_relative "helpers/artifice"
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointMarshalFail < EndpointFallback
|
|
||||||
get "/api/v1/dependencies" do
|
|
||||||
"f0283y01hasf"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Artifice.activate_with(EndpointMarshalFail)
|
Artifice.activate_with(EndpointMarshalFail)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint_marshal_fail"
|
require_relative "helpers/endpoint_marshal_fail"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointMarshalFailBasicAuthentication < EndpointMarshalFail
|
class EndpointMarshalFailBasicAuthentication < EndpointMarshalFail
|
||||||
before do
|
before do
|
||||||
@ -12,4 +10,6 @@ class EndpointMarshalFailBasicAuthentication < EndpointMarshalFail
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointMarshalFailBasicAuthentication)
|
Artifice.activate_with(EndpointMarshalFailBasicAuthentication)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
class EndpointMirrorSource < Endpoint
|
class EndpointMirrorSource < Endpoint
|
||||||
get "/gems/:id" do
|
get "/gems/:id" do
|
||||||
@ -12,4 +12,6 @@ class EndpointMirrorSource < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointMirrorSource)
|
Artifice.activate_with(EndpointMirrorSource)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointRedirect < Endpoint
|
class EndpointRedirect < Endpoint
|
||||||
get "/fetch/actual/gem/:id" do
|
get "/fetch/actual/gem/:id" do
|
||||||
@ -14,4 +12,6 @@ class EndpointRedirect < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointRedirect)
|
Artifice.activate_with(EndpointRedirect)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint"
|
require_relative "helpers/endpoint"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointStrictBasicAuthentication < Endpoint
|
class EndpointStrictBasicAuthentication < Endpoint
|
||||||
before do
|
before do
|
||||||
@ -17,4 +15,6 @@ class EndpointStrictBasicAuthentication < Endpoint
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointStrictBasicAuthentication)
|
Artifice.activate_with(EndpointStrictBasicAuthentication)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "endpoint_fallback"
|
require_relative "helpers/endpoint_fallback"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class EndpointTimeout < EndpointFallback
|
class EndpointTimeout < EndpointFallback
|
||||||
SLEEP_TIMEOUT = 3
|
SLEEP_TIMEOUT = 3
|
||||||
@ -12,4 +10,6 @@ class EndpointTimeout < EndpointFallback
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(EndpointTimeout)
|
Artifice.activate_with(EndpointTimeout)
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
require "net/http"
|
require "net/http"
|
||||||
|
|
||||||
# We can't use artifice here because it uses rack
|
|
||||||
|
|
||||||
module Artifice; end # for < 2.0, Net::HTTP::Persistent::SSLReuse
|
|
||||||
|
|
||||||
class Fail < Net::HTTP
|
class Fail < Net::HTTP
|
||||||
# Net::HTTP uses a @newimpl instance variable to decide whether
|
# Net::HTTP uses a @newimpl instance variable to decide whether
|
||||||
# to use a legacy implementation. Since we are subclassing
|
# to use a legacy implementation. Since we are subclassing
|
||||||
@ -27,8 +23,7 @@ class Fail < Net::HTTP
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
# Replace Net::HTTP with our failing subclass
|
# Replace Net::HTTP with our failing subclass
|
||||||
::Net.class_eval do
|
Artifice.replace_net_http(::Fail)
|
||||||
remove_const(:HTTP)
|
|
||||||
const_set(:HTTP, ::Fail)
|
|
||||||
end
|
|
||||||
|
30
spec/bundler/support/artifice/helpers/artifice.rb
Normal file
30
spec/bundler/support/artifice/helpers/artifice.rb
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# This module was initially borrowed from https://github.com/wycats/artifice
|
||||||
|
module Artifice
|
||||||
|
# Activate Artifice with a particular Rack endpoint.
|
||||||
|
#
|
||||||
|
# Calling this method will replace the Net::HTTP system
|
||||||
|
# with a replacement that routes all requests to the
|
||||||
|
# Rack endpoint.
|
||||||
|
#
|
||||||
|
# @param [#call] endpoint A valid Rack endpoint
|
||||||
|
def self.activate_with(endpoint)
|
||||||
|
require_relative "rack_request"
|
||||||
|
|
||||||
|
Net::HTTP.endpoint = endpoint
|
||||||
|
replace_net_http(Artifice::Net::HTTP)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Deactivate the Artifice replacement.
|
||||||
|
def self.deactivate
|
||||||
|
replace_net_http(::Net::HTTP)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.replace_net_http(value)
|
||||||
|
::Net.class_eval do
|
||||||
|
remove_const(:HTTP)
|
||||||
|
const_set(:HTTP, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
118
spec/bundler/support/artifice/helpers/compact_index.rb
Normal file
118
spec/bundler/support/artifice/helpers/compact_index.rb
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "endpoint"
|
||||||
|
|
||||||
|
$LOAD_PATH.unshift Dir[Spec::Path.base_system_gem_path.join("gems/compact_index*/lib")].first.to_s
|
||||||
|
require "compact_index"
|
||||||
|
|
||||||
|
class CompactIndexAPI < Endpoint
|
||||||
|
helpers do
|
||||||
|
include Spec::Path
|
||||||
|
|
||||||
|
def load_spec(name, version, platform, gem_repo)
|
||||||
|
full_name = "#{name}-#{version}"
|
||||||
|
full_name += "-#{platform}" if platform != "ruby"
|
||||||
|
Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
|
||||||
|
end
|
||||||
|
|
||||||
|
def etag_response
|
||||||
|
response_body = yield
|
||||||
|
checksum = Digest(:MD5).hexdigest(response_body)
|
||||||
|
return if not_modified?(checksum)
|
||||||
|
headers "ETag" => quote(checksum)
|
||||||
|
headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
|
||||||
|
content_type "text/plain"
|
||||||
|
requested_range_for(response_body)
|
||||||
|
rescue StandardError => e
|
||||||
|
puts e
|
||||||
|
puts e.backtrace
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
|
||||||
|
def not_modified?(checksum)
|
||||||
|
etags = parse_etags(request.env["HTTP_IF_NONE_MATCH"])
|
||||||
|
|
||||||
|
return unless etags.include?(checksum)
|
||||||
|
headers "ETag" => quote(checksum)
|
||||||
|
status 304
|
||||||
|
body ""
|
||||||
|
end
|
||||||
|
|
||||||
|
def requested_range_for(response_body)
|
||||||
|
ranges = Rack::Utils.byte_ranges(env, response_body.bytesize)
|
||||||
|
|
||||||
|
if ranges
|
||||||
|
status 206
|
||||||
|
body ranges.map! {|range| slice_body(response_body, range) }.join
|
||||||
|
else
|
||||||
|
status 200
|
||||||
|
body response_body
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def quote(string)
|
||||||
|
%("#{string}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_etags(value)
|
||||||
|
value ? value.split(/, ?/).select {|s| s.sub!(/"(.*)"/, '\1') } : []
|
||||||
|
end
|
||||||
|
|
||||||
|
def slice_body(body, range)
|
||||||
|
body.byteslice(range)
|
||||||
|
end
|
||||||
|
|
||||||
|
def gems(gem_repo = default_gem_repo)
|
||||||
|
@gems ||= {}
|
||||||
|
@gems[gem_repo] ||= begin
|
||||||
|
specs = Bundler::Deprecate.skip_during do
|
||||||
|
%w[specs.4.8 prerelease_specs.4.8].map do |filename|
|
||||||
|
Marshal.load(File.open(gem_repo.join(filename)).read).map do |name, version, platform|
|
||||||
|
load_spec(name, version, platform, gem_repo)
|
||||||
|
end
|
||||||
|
end.flatten
|
||||||
|
end
|
||||||
|
|
||||||
|
specs.group_by(&:name).map do |name, versions|
|
||||||
|
gem_versions = versions.map do |spec|
|
||||||
|
deps = spec.dependencies.select {|d| d.type == :runtime }.map do |d|
|
||||||
|
reqs = d.requirement.requirements.map {|r| r.join(" ") }.join(", ")
|
||||||
|
CompactIndex::Dependency.new(d.name, reqs)
|
||||||
|
end
|
||||||
|
checksum = begin
|
||||||
|
Digest(:SHA256).file("#{gem_repo}/gems/#{spec.original_name}.gem").base64digest
|
||||||
|
rescue StandardError
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
CompactIndex::GemVersion.new(spec.version.version, spec.platform.to_s, checksum, nil,
|
||||||
|
deps, spec.required_ruby_version.to_s, spec.required_rubygems_version.to_s)
|
||||||
|
end
|
||||||
|
CompactIndex::Gem.new(name, gem_versions)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/names" do
|
||||||
|
etag_response do
|
||||||
|
CompactIndex.names(gems.map(&:name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/versions" do
|
||||||
|
etag_response do
|
||||||
|
file = tmp("versions.list")
|
||||||
|
FileUtils.rm_f(file)
|
||||||
|
file = CompactIndex::VersionsFile.new(file.to_s)
|
||||||
|
file.create(gems)
|
||||||
|
file.contents
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/info/:name" do
|
||||||
|
etag_response do
|
||||||
|
gem = gems.find {|g| g.name == params[:name] }
|
||||||
|
CompactIndex.info(gem ? gem.versions : [])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
33
spec/bundler/support/artifice/helpers/compact_index_extra.rb
Normal file
33
spec/bundler/support/artifice/helpers/compact_index_extra.rb
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "compact_index"
|
||||||
|
|
||||||
|
class CompactIndexExtra < CompactIndexAPI
|
||||||
|
get "/extra/versions" do
|
||||||
|
halt 404
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/api/v1/dependencies" do
|
||||||
|
halt 404
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/specs.4.8.gz" do
|
||||||
|
File.binread("#{gem_repo2}/specs.4.8.gz")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/prerelease_specs.4.8.gz" do
|
||||||
|
File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/quick/Marshal.4.8/:id" do
|
||||||
|
redirect "/extra/fetch/actual/gem/#{params[:id]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/fetch/actual/gem/:id" do
|
||||||
|
File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/gems/:id" do
|
||||||
|
File.binread("#{gem_repo2}/gems/#{params[:id]}")
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,48 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "compact_index"
|
||||||
|
|
||||||
|
class CompactIndexExtraApi < CompactIndexAPI
|
||||||
|
get "/extra/names" do
|
||||||
|
etag_response do
|
||||||
|
CompactIndex.names(gems(gem_repo4).map(&:name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/versions" do
|
||||||
|
etag_response do
|
||||||
|
file = tmp("versions.list")
|
||||||
|
FileUtils.rm_f(file)
|
||||||
|
file = CompactIndex::VersionsFile.new(file.to_s)
|
||||||
|
file.create(gems(gem_repo4))
|
||||||
|
file.contents
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/info/:name" do
|
||||||
|
etag_response do
|
||||||
|
gem = gems(gem_repo4).find {|g| g.name == params[:name] }
|
||||||
|
CompactIndex.info(gem ? gem.versions : [])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/specs.4.8.gz" do
|
||||||
|
File.binread("#{gem_repo4}/specs.4.8.gz")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/prerelease_specs.4.8.gz" do
|
||||||
|
File.binread("#{gem_repo4}/prerelease_specs.4.8.gz")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/quick/Marshal.4.8/:id" do
|
||||||
|
redirect "/extra/fetch/actual/gem/#{params[:id]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/fetch/actual/gem/:id" do
|
||||||
|
File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/gems/:id" do
|
||||||
|
File.binread("#{gem_repo4}/gems/#{params[:id]}")
|
||||||
|
end
|
||||||
|
end
|
112
spec/bundler/support/artifice/helpers/endpoint.rb
Normal file
112
spec/bundler/support/artifice/helpers/endpoint.rb
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "../../path"
|
||||||
|
|
||||||
|
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
|
||||||
|
|
||||||
|
require "sinatra/base"
|
||||||
|
|
||||||
|
ALL_REQUESTS = [] # rubocop:disable Style/MutableConstant
|
||||||
|
ALL_REQUESTS_MUTEX = Thread::Mutex.new
|
||||||
|
|
||||||
|
at_exit do
|
||||||
|
if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"]
|
||||||
|
expected = expected.split("\n").sort
|
||||||
|
actual = ALL_REQUESTS.sort
|
||||||
|
|
||||||
|
unless expected == actual
|
||||||
|
raise "Unexpected requests!\nExpected:\n\t#{expected.join("\n\t")}\n\nActual:\n\t#{actual.join("\n\t")}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Endpoint < Sinatra::Base
|
||||||
|
def self.all_requests
|
||||||
|
@all_requests ||= []
|
||||||
|
end
|
||||||
|
|
||||||
|
set :raise_errors, true
|
||||||
|
set :show_exceptions, false
|
||||||
|
|
||||||
|
def call!(*)
|
||||||
|
super.tap do
|
||||||
|
ALL_REQUESTS_MUTEX.synchronize do
|
||||||
|
ALL_REQUESTS << @request.url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
helpers do
|
||||||
|
include Spec::Path
|
||||||
|
|
||||||
|
def default_gem_repo
|
||||||
|
if ENV["BUNDLER_SPEC_GEM_REPO"]
|
||||||
|
Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"])
|
||||||
|
else
|
||||||
|
case request.host
|
||||||
|
when "gem.repo1"
|
||||||
|
Spec::Path.gem_repo1
|
||||||
|
when "gem.repo2"
|
||||||
|
Spec::Path.gem_repo2
|
||||||
|
when "gem.repo3"
|
||||||
|
Spec::Path.gem_repo3
|
||||||
|
when "gem.repo4"
|
||||||
|
Spec::Path.gem_repo4
|
||||||
|
else
|
||||||
|
Spec::Path.gem_repo1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def dependencies_for(gem_names, gem_repo = default_gem_repo)
|
||||||
|
return [] if gem_names.nil? || gem_names.empty?
|
||||||
|
|
||||||
|
all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename|
|
||||||
|
Marshal.load(File.open(gem_repo.join(filename)).read)
|
||||||
|
end.inject(:+)
|
||||||
|
|
||||||
|
all_specs.map do |name, version, platform|
|
||||||
|
spec = load_spec(name, version, platform, gem_repo)
|
||||||
|
next unless gem_names.include?(spec.name)
|
||||||
|
{
|
||||||
|
:name => spec.name,
|
||||||
|
:number => spec.version.version,
|
||||||
|
:platform => spec.platform.to_s,
|
||||||
|
:dependencies => spec.dependencies.select {|dep| dep.type == :runtime }.map do |dep|
|
||||||
|
[dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")]
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end.compact
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_spec(name, version, platform, gem_repo)
|
||||||
|
full_name = "#{name}-#{version}"
|
||||||
|
full_name += "-#{platform}" if platform != "ruby"
|
||||||
|
Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/quick/Marshal.4.8/:id" do
|
||||||
|
redirect "/fetch/actual/gem/#{params[:id]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/fetch/actual/gem/:id" do
|
||||||
|
File.binread("#{default_gem_repo}/quick/Marshal.4.8/#{params[:id]}")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/gems/:id" do
|
||||||
|
File.binread("#{default_gem_repo}/gems/#{params[:id]}")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/api/v1/dependencies" do
|
||||||
|
Marshal.dump(dependencies_for(params[:gems]))
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/specs.4.8.gz" do
|
||||||
|
File.binread("#{default_gem_repo}/specs.4.8.gz")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/prerelease_specs.4.8.gz" do
|
||||||
|
File.binread("#{default_gem_repo}/prerelease_specs.4.8.gz")
|
||||||
|
end
|
||||||
|
end
|
29
spec/bundler/support/artifice/helpers/endpoint_extra.rb
Normal file
29
spec/bundler/support/artifice/helpers/endpoint_extra.rb
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "endpoint"
|
||||||
|
|
||||||
|
class EndpointExtra < Endpoint
|
||||||
|
get "/extra/api/v1/dependencies" do
|
||||||
|
halt 404
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/specs.4.8.gz" do
|
||||||
|
File.binread("#{gem_repo2}/specs.4.8.gz")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/prerelease_specs.4.8.gz" do
|
||||||
|
File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/quick/Marshal.4.8/:id" do
|
||||||
|
redirect "/extra/fetch/actual/gem/#{params[:id]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/fetch/actual/gem/:id" do
|
||||||
|
File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/extra/gems/:id" do
|
||||||
|
File.binread("#{gem_repo2}/gems/#{params[:id]}")
|
||||||
|
end
|
||||||
|
end
|
15
spec/bundler/support/artifice/helpers/endpoint_fallback.rb
Normal file
15
spec/bundler/support/artifice/helpers/endpoint_fallback.rb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "endpoint"
|
||||||
|
|
||||||
|
class EndpointFallback < Endpoint
|
||||||
|
DEPENDENCY_LIMIT = 60
|
||||||
|
|
||||||
|
get "/api/v1/dependencies" do
|
||||||
|
if params[:gems] && params[:gems].size <= DEPENDENCY_LIMIT
|
||||||
|
Marshal.dump(dependencies_for(params[:gems]))
|
||||||
|
else
|
||||||
|
halt 413, "Too many gems to resolve, please request less than #{DEPENDENCY_LIMIT} gems"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "endpoint_fallback"
|
||||||
|
|
||||||
|
class EndpointMarshalFail < EndpointFallback
|
||||||
|
get "/api/v1/dependencies" do
|
||||||
|
"f0283y01hasf"
|
||||||
|
end
|
||||||
|
end
|
100
spec/bundler/support/artifice/helpers/rack_request.rb
Normal file
100
spec/bundler/support/artifice/helpers/rack_request.rb
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rack/test"
|
||||||
|
require "net/http"
|
||||||
|
|
||||||
|
module Artifice
|
||||||
|
module Net
|
||||||
|
# This is an internal object that can receive Rack requests
|
||||||
|
# to the application using the Rack::Test API
|
||||||
|
class RackRequest
|
||||||
|
include Rack::Test::Methods
|
||||||
|
attr_reader :app
|
||||||
|
|
||||||
|
def initialize(app)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class HTTP < ::Net::HTTP
|
||||||
|
class << self
|
||||||
|
attr_accessor :endpoint
|
||||||
|
end
|
||||||
|
|
||||||
|
# Net::HTTP uses a @newimpl instance variable to decide whether
|
||||||
|
# to use a legacy implementation. Since we are subclassing
|
||||||
|
# Net::HTTP, we must set it
|
||||||
|
@newimpl = true
|
||||||
|
|
||||||
|
# We don't need to connect, so blank out this method
|
||||||
|
def connect
|
||||||
|
end
|
||||||
|
|
||||||
|
# Replace the Net::HTTP request method with a method
|
||||||
|
# that converts the request into a Rack request and
|
||||||
|
# dispatches it to the Rack endpoint.
|
||||||
|
#
|
||||||
|
# @param [Net::HTTPRequest] req A Net::HTTPRequest
|
||||||
|
# object, or one if its subclasses
|
||||||
|
# @param [optional, String, #read] body This should
|
||||||
|
# be sent as "rack.input". If it's a String, it will
|
||||||
|
# be converted to a StringIO.
|
||||||
|
# @return [Net::HTTPResponse]
|
||||||
|
#
|
||||||
|
# @yield [Net::HTTPResponse] If a block is provided,
|
||||||
|
# this method will yield the Net::HTTPResponse to
|
||||||
|
# it after the body is read.
|
||||||
|
def request(req, body = nil, &block)
|
||||||
|
rack_request = RackRequest.new(self.class.endpoint)
|
||||||
|
|
||||||
|
req.each_header do |header, value|
|
||||||
|
rack_request.header(header, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
scheme = use_ssl? ? "https" : "http"
|
||||||
|
prefix = "#{scheme}://#{addr_port}"
|
||||||
|
body_stream_contents = req.body_stream.read if req.body_stream
|
||||||
|
|
||||||
|
response = rack_request.request("#{prefix}#{req.path}",
|
||||||
|
{ :method => req.method, :input => body || req.body || body_stream_contents })
|
||||||
|
|
||||||
|
make_net_http_response(response, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# This method takes a Rack response and creates a Net::HTTPResponse
|
||||||
|
# Instead of trying to mock HTTPResponse directly, we just convert
|
||||||
|
# the Rack response into a String that looks like a normal HTTP
|
||||||
|
# response and call Net::HTTPResponse.read_new
|
||||||
|
#
|
||||||
|
# @param [Array(#to_i, Hash, #each)] response a Rack response
|
||||||
|
# @return [Net::HTTPResponse]
|
||||||
|
# @yield [Net::HTTPResponse] If a block is provided, yield the
|
||||||
|
# response to it after the body is read
|
||||||
|
def make_net_http_response(response)
|
||||||
|
status = response.status
|
||||||
|
headers = response.headers
|
||||||
|
body = response.body
|
||||||
|
|
||||||
|
response_string = []
|
||||||
|
response_string << "HTTP/1.1 #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}"
|
||||||
|
|
||||||
|
headers.each do |header, value|
|
||||||
|
response_string << "#{header}: #{value}"
|
||||||
|
end
|
||||||
|
|
||||||
|
response_string << "" << body
|
||||||
|
|
||||||
|
response_io = ::Net::BufferedIO.new(StringIO.new(response_string.join("\n")))
|
||||||
|
res = ::Net::HTTPResponse.read_new(response_io)
|
||||||
|
|
||||||
|
res.reading_body(response_io, true) do
|
||||||
|
yield res if block_given?
|
||||||
|
end
|
||||||
|
|
||||||
|
res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -158,8 +158,7 @@ class BundlerVCRHTTP < Net::HTTP
|
|||||||
alias_method :request, :request_with_vcr
|
alias_method :request, :request_with_vcr
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
# Replace Net::HTTP with our VCR subclass
|
# Replace Net::HTTP with our VCR subclass
|
||||||
::Net.class_eval do
|
Artifice.replace_net_http(BundlerVCRHTTP)
|
||||||
remove_const(:HTTP)
|
|
||||||
const_set(:HTTP, BundlerVCRHTTP)
|
|
||||||
end
|
|
||||||
|
@ -2,13 +2,10 @@
|
|||||||
|
|
||||||
require_relative "../path"
|
require_relative "../path"
|
||||||
|
|
||||||
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
|
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
|
||||||
|
|
||||||
require "artifice"
|
|
||||||
require "sinatra/base"
|
require "sinatra/base"
|
||||||
|
|
||||||
Artifice.deactivate
|
|
||||||
|
|
||||||
class Windows < Sinatra::Base
|
class Windows < Sinatra::Base
|
||||||
set :raise_errors, true
|
set :raise_errors, true
|
||||||
set :show_exceptions, false
|
set :show_exceptions, false
|
||||||
@ -43,4 +40,6 @@ class Windows < Sinatra::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "helpers/artifice"
|
||||||
|
|
||||||
Artifice.activate_with(Windows)
|
Artifice.activate_with(Windows)
|
||||||
|
@ -5,7 +5,6 @@ source "https://rubygems.org"
|
|||||||
gem "rack", "2.0.8"
|
gem "rack", "2.0.8"
|
||||||
gem "webrick", "1.7.0"
|
gem "webrick", "1.7.0"
|
||||||
gem "rack-test", "~> 1.1"
|
gem "rack-test", "~> 1.1"
|
||||||
gem "artifice", "~> 0.6.0"
|
|
||||||
gem "compact_index", "~> 0.13.0"
|
gem "compact_index", "~> 0.13.0"
|
||||||
gem "sinatra", "~> 2.0"
|
gem "sinatra", "~> 2.0"
|
||||||
gem "rake", "13.0.1"
|
gem "rake", "13.0.1"
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
artifice (0.6)
|
|
||||||
rack-test
|
|
||||||
builder (3.2.4)
|
builder (3.2.4)
|
||||||
compact_index (0.13.0)
|
compact_index (0.13.0)
|
||||||
mustermann (1.1.2)
|
mustermann (1.1.2)
|
||||||
@ -33,7 +31,6 @@ PLATFORMS
|
|||||||
x86_64-linux
|
x86_64-linux
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
artifice (~> 0.6.0)
|
|
||||||
builder (~> 3.2)
|
builder (~> 3.2)
|
||||||
compact_index (~> 0.13.0)
|
compact_index (~> 0.13.0)
|
||||||
rack (= 2.0.8)
|
rack (= 2.0.8)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user