mirror of
https://github.com/ruby/ruby.git
synced 2025-08-25 14:05:02 +02:00

Looks for the CHECKSUMS section in the lockfile, activating the feature
only if the section exists. Without a CHECKSUMS section, Bundler will
continue as normal, validating checksums when gems are installed while
checksums from the compact index are present.
2353cc93a4
460 lines
12 KiB
Ruby
460 lines
12 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe "real source plugins" do
|
|
context "with a minimal source plugin" do
|
|
before do
|
|
build_repo2 do
|
|
build_plugin "bundler-source-mpath" do |s|
|
|
s.write "plugins.rb", <<-RUBY
|
|
require "bundler-source-mpath"
|
|
|
|
class MPath < Bundler::Plugin::API
|
|
source "mpath"
|
|
|
|
attr_reader :path
|
|
|
|
def initialize(opts)
|
|
super
|
|
|
|
@path = Pathname.new options["uri"]
|
|
end
|
|
|
|
def fetch_gemspec_files
|
|
@spec_files ||= begin
|
|
glob = "{,*,*/*}.gemspec"
|
|
if installed?
|
|
search_path = install_path
|
|
else
|
|
search_path = path
|
|
end
|
|
Dir["\#{search_path.to_s}/\#{glob}"]
|
|
end
|
|
end
|
|
|
|
def install(spec, opts)
|
|
mkdir_p(install_path.parent)
|
|
require 'fileutils'
|
|
FileUtils.cp_r(path, install_path)
|
|
|
|
spec_path = install_path.join("\#{spec.full_name}.gemspec")
|
|
spec_path.open("wb") {|f| f.write spec.to_ruby }
|
|
spec.loaded_from = spec_path.to_s
|
|
|
|
post_install(spec)
|
|
|
|
nil
|
|
end
|
|
end
|
|
RUBY
|
|
end # build_plugin
|
|
end
|
|
|
|
build_lib "a-path-gem"
|
|
|
|
gemfile <<-G
|
|
source "#{file_uri_for(gem_repo2)}" # plugin source
|
|
source "#{lib_path("a-path-gem-1.0")}", :type => :mpath do
|
|
gem "a-path-gem"
|
|
end
|
|
G
|
|
end
|
|
|
|
it "installs" do
|
|
bundle "install"
|
|
|
|
expect(out).to include("Bundle complete!")
|
|
|
|
expect(the_bundle).to include_gems("a-path-gem 1.0")
|
|
end
|
|
|
|
it "writes to lock file" do
|
|
bundle "install"
|
|
|
|
checksums = checksums_section_when_existing do |c|
|
|
c.no_checksum "a-path-gem", "1.0"
|
|
end
|
|
|
|
expect(lockfile).to eq <<~G
|
|
PLUGIN SOURCE
|
|
remote: #{lib_path("a-path-gem-1.0")}
|
|
type: mpath
|
|
specs:
|
|
a-path-gem (1.0)
|
|
|
|
GEM
|
|
remote: #{file_uri_for(gem_repo2)}/
|
|
specs:
|
|
|
|
PLATFORMS
|
|
#{lockfile_platforms}
|
|
|
|
DEPENDENCIES
|
|
a-path-gem!
|
|
#{checksums}
|
|
BUNDLED WITH
|
|
#{Bundler::VERSION}
|
|
G
|
|
end
|
|
|
|
it "provides correct #full_gem_path" do
|
|
bundle "install"
|
|
run <<-RUBY
|
|
puts Bundler.rubygems.find_name('a-path-gem').first.full_gem_path
|
|
RUBY
|
|
expect(out).to eq(bundle("info a-path-gem --path"))
|
|
end
|
|
|
|
it "installs the gem executables" do
|
|
build_lib "gem_with_bin" do |s|
|
|
s.executables = ["foo"]
|
|
end
|
|
|
|
install_gemfile <<-G
|
|
source "#{file_uri_for(gem_repo2)}" # plugin source
|
|
source "#{lib_path("gem_with_bin-1.0")}", :type => :mpath do
|
|
gem "gem_with_bin"
|
|
end
|
|
G
|
|
|
|
bundle "exec foo"
|
|
expect(out).to eq("1.0")
|
|
end
|
|
|
|
describe "bundle cache/package" do
|
|
let(:uri_hash) { Digest(:SHA1).hexdigest(lib_path("a-path-gem-1.0").to_s) }
|
|
it "copies repository to vendor cache and uses it" do
|
|
bundle "install"
|
|
bundle "config set cache_all true"
|
|
bundle :cache
|
|
|
|
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
|
|
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}/.git")).not_to exist
|
|
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}/.bundlecache")).to be_file
|
|
|
|
FileUtils.rm_rf lib_path("a-path-gem-1.0")
|
|
expect(the_bundle).to include_gems("a-path-gem 1.0")
|
|
end
|
|
|
|
it "copies repository to vendor cache and uses it even when installed with `path` configured" do
|
|
bundle "config set --local path vendor/bundle"
|
|
bundle :install
|
|
bundle "config set cache_all true"
|
|
bundle :cache
|
|
|
|
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
|
|
|
|
FileUtils.rm_rf lib_path("a-path-gem-1.0")
|
|
expect(the_bundle).to include_gems("a-path-gem 1.0")
|
|
end
|
|
|
|
it "bundler package copies repository to vendor cache" do
|
|
bundle "config set --local path vendor/bundle"
|
|
bundle :install
|
|
bundle "config set cache_all true"
|
|
bundle :cache
|
|
|
|
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
|
|
|
|
FileUtils.rm_rf lib_path("a-path-gem-1.0")
|
|
expect(the_bundle).to include_gems("a-path-gem 1.0")
|
|
end
|
|
end
|
|
|
|
context "with lockfile" do
|
|
before do
|
|
lockfile <<-G
|
|
PLUGIN SOURCE
|
|
remote: #{lib_path("a-path-gem-1.0")}
|
|
type: mpath
|
|
specs:
|
|
a-path-gem (1.0)
|
|
|
|
GEM
|
|
remote: #{file_uri_for(gem_repo2)}/
|
|
specs:
|
|
|
|
PLATFORMS
|
|
#{generic_local_platform}
|
|
|
|
DEPENDENCIES
|
|
a-path-gem!
|
|
|
|
BUNDLED WITH
|
|
#{Bundler::VERSION}
|
|
G
|
|
end
|
|
|
|
it "installs" do
|
|
bundle "install"
|
|
|
|
expect(the_bundle).to include_gems("a-path-gem 1.0")
|
|
end
|
|
end
|
|
end
|
|
|
|
context "with a more elaborate source plugin" do
|
|
before do
|
|
build_repo2 do
|
|
build_plugin "bundler-source-gitp" do |s|
|
|
s.write "plugins.rb", <<-RUBY
|
|
require "open3"
|
|
|
|
class SPlugin < Bundler::Plugin::API
|
|
source "gitp"
|
|
|
|
attr_reader :ref
|
|
|
|
def initialize(opts)
|
|
super
|
|
|
|
@ref = options["ref"] || options["branch"] || options["tag"] || "main"
|
|
@unlocked = false
|
|
end
|
|
|
|
def eql?(other)
|
|
other.is_a?(self.class) && uri == other.uri && ref == other.ref
|
|
end
|
|
|
|
alias_method :==, :eql?
|
|
|
|
def fetch_gemspec_files
|
|
@spec_files ||= begin
|
|
glob = "{,*,*/*}.gemspec"
|
|
if !cached?
|
|
cache_repo
|
|
end
|
|
|
|
if installed? && !@unlocked
|
|
path = install_path
|
|
else
|
|
path = cache_path
|
|
end
|
|
|
|
Dir["\#{path}/\#{glob}"]
|
|
end
|
|
end
|
|
|
|
def install(spec, opts)
|
|
mkdir_p(install_path.dirname)
|
|
rm_rf(install_path)
|
|
`git clone --no-checkout --quiet "\#{cache_path}" "\#{install_path}"`
|
|
Open3.capture2e("git reset --hard \#{revision}", :chdir => install_path)
|
|
|
|
spec_path = install_path.join("\#{spec.full_name}.gemspec")
|
|
spec_path.open("wb") {|f| f.write spec.to_ruby }
|
|
spec.loaded_from = spec_path.to_s
|
|
|
|
post_install(spec)
|
|
|
|
nil
|
|
end
|
|
|
|
def options_to_lock
|
|
opts = {"revision" => revision}
|
|
opts["ref"] = ref if ref != "main"
|
|
opts
|
|
end
|
|
|
|
def unlock!
|
|
@unlocked = true
|
|
@revision = latest_revision
|
|
end
|
|
|
|
def app_cache_dirname
|
|
"\#{base_name}-\#{shortref_for_path(revision)}"
|
|
end
|
|
|
|
private
|
|
|
|
def cache_path
|
|
@cache_path ||= cache_dir.join("gitp", base_name)
|
|
end
|
|
|
|
def cache_repo
|
|
`git clone --quiet \#{@options["uri"]} \#{cache_path}`
|
|
end
|
|
|
|
def cached?
|
|
File.directory?(cache_path)
|
|
end
|
|
|
|
def locked_revision
|
|
options["revision"]
|
|
end
|
|
|
|
def revision
|
|
@revision ||= locked_revision || latest_revision
|
|
end
|
|
|
|
def latest_revision
|
|
if !cached? || @unlocked
|
|
rm_rf(cache_path)
|
|
cache_repo
|
|
end
|
|
|
|
output, _status = Open3.capture2e("git rev-parse --verify \#{@ref}", :chdir => cache_path)
|
|
output.strip
|
|
end
|
|
|
|
def base_name
|
|
File.basename(uri.sub(%r{^(\w+://)?([^/:]+:)?(//\w*/)?(\w*/)*}, ""), ".git")
|
|
end
|
|
|
|
def shortref_for_path(ref)
|
|
ref[0..11]
|
|
end
|
|
|
|
def install_path
|
|
@install_path ||= begin
|
|
git_scope = "\#{base_name}-\#{shortref_for_path(revision)}"
|
|
|
|
gem_install_dir.join(git_scope)
|
|
end
|
|
end
|
|
|
|
def installed?
|
|
File.directory?(install_path)
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
|
|
build_git "ma-gitp-gem"
|
|
|
|
gemfile <<-G
|
|
source "#{file_uri_for(gem_repo2)}" # plugin source
|
|
source "#{file_uri_for(lib_path("ma-gitp-gem-1.0"))}", :type => :gitp do
|
|
gem "ma-gitp-gem"
|
|
end
|
|
G
|
|
end
|
|
|
|
it "handles the source option" do
|
|
bundle "install"
|
|
expect(out).to include("Bundle complete!")
|
|
expect(the_bundle).to include_gems("ma-gitp-gem 1.0")
|
|
end
|
|
|
|
it "writes to lock file" do
|
|
revision = revision_for(lib_path("ma-gitp-gem-1.0"))
|
|
bundle "install"
|
|
|
|
checksums = checksums_section_when_existing do |c|
|
|
c.no_checksum "ma-gitp-gem", "1.0"
|
|
end
|
|
|
|
expect(lockfile).to eq <<~G
|
|
PLUGIN SOURCE
|
|
remote: #{file_uri_for(lib_path("ma-gitp-gem-1.0"))}
|
|
type: gitp
|
|
revision: #{revision}
|
|
specs:
|
|
ma-gitp-gem (1.0)
|
|
|
|
GEM
|
|
remote: #{file_uri_for(gem_repo2)}/
|
|
specs:
|
|
|
|
PLATFORMS
|
|
#{lockfile_platforms}
|
|
|
|
DEPENDENCIES
|
|
ma-gitp-gem!
|
|
#{checksums}
|
|
BUNDLED WITH
|
|
#{Bundler::VERSION}
|
|
G
|
|
end
|
|
|
|
context "with lockfile" do
|
|
before do
|
|
revision = revision_for(lib_path("ma-gitp-gem-1.0"))
|
|
lockfile <<-G
|
|
PLUGIN SOURCE
|
|
remote: #{file_uri_for(lib_path("ma-gitp-gem-1.0"))}
|
|
type: gitp
|
|
revision: #{revision}
|
|
specs:
|
|
ma-gitp-gem (1.0)
|
|
|
|
GEM
|
|
remote: #{file_uri_for(gem_repo2)}/
|
|
specs:
|
|
|
|
PLATFORMS
|
|
#{generic_local_platform}
|
|
|
|
DEPENDENCIES
|
|
ma-gitp-gem!
|
|
|
|
BUNDLED WITH
|
|
#{Bundler::VERSION}
|
|
G
|
|
end
|
|
|
|
it "installs" do
|
|
bundle "install"
|
|
expect(the_bundle).to include_gems("ma-gitp-gem 1.0")
|
|
end
|
|
|
|
it "uses the locked ref" do
|
|
update_git "ma-gitp-gem"
|
|
bundle "install"
|
|
|
|
run <<-RUBY
|
|
require 'ma/gitp/gem'
|
|
puts "WIN" unless defined?(MAGITPGEM_PREV_REF)
|
|
RUBY
|
|
expect(out).to eq("WIN")
|
|
end
|
|
|
|
it "updates the deps on bundler update" do
|
|
update_git "ma-gitp-gem"
|
|
bundle "update ma-gitp-gem"
|
|
|
|
run <<-RUBY
|
|
require 'ma/gitp/gem'
|
|
puts "WIN" if defined?(MAGITPGEM_PREV_REF)
|
|
RUBY
|
|
expect(out).to eq("WIN")
|
|
end
|
|
|
|
it "updates the deps on change in gemfile" do
|
|
update_git "ma-gitp-gem", "1.1", :path => lib_path("ma-gitp-gem-1.0"), :gemspec => true
|
|
gemfile <<-G
|
|
source "#{file_uri_for(gem_repo2)}" # plugin source
|
|
source "#{file_uri_for(lib_path("ma-gitp-gem-1.0"))}", :type => :gitp do
|
|
gem "ma-gitp-gem", "1.1"
|
|
end
|
|
G
|
|
bundle "install"
|
|
|
|
expect(the_bundle).to include_gems("ma-gitp-gem 1.1")
|
|
end
|
|
end
|
|
|
|
describe "bundle cache with gitp" do
|
|
it "copies repository to vendor cache and uses it" do
|
|
git = build_git "foo"
|
|
ref = git.ref_for("main", 11)
|
|
|
|
install_gemfile <<-G
|
|
source "#{file_uri_for(gem_repo2)}" # plugin source
|
|
source '#{lib_path("foo-1.0")}', :type => :gitp do
|
|
gem "foo"
|
|
end
|
|
G
|
|
|
|
bundle "config set cache_all true"
|
|
bundle :cache
|
|
expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
|
|
expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist
|
|
expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.bundlecache")).to be_file
|
|
|
|
FileUtils.rm_rf lib_path("foo-1.0")
|
|
expect(the_bundle).to include_gems "foo 1.0"
|
|
end
|
|
end
|
|
end
|
|
end
|