diff --git a/lib/bundler/plugin/api/source.rb b/lib/bundler/plugin/api/source.rb index dad2e59024f..f7f80c1b283 100644 --- a/lib/bundler/plugin/api/source.rb +++ b/lib/bundler/plugin/api/source.rb @@ -1,4 +1,6 @@ # frozen_string_literal: true +require "uri" +require "digest/sha1" module Bundler module Plugin @@ -50,7 +52,8 @@ def to_lock out << " specs:\n" end - def install + def install(spec, opts) + raise MalformattedPlugin, "Source plugins need to override the install method." end def fetch_gemfiles @@ -64,9 +67,37 @@ def options_to_lock def remote! end + def cache! + end + def include?(other) other == self end + + def ==(other) + other.is_a?(self.class) && uri == other.uri + end + + def uri_hash + Digest::SHA1.hexdigest(uri) + end + + def gem_install_dir + Bundler.install_path + end + + def install_path + @install_path ||= + begin + base_name = File.basename(URI.parse(uri).normalize.path) + + gem_install_dir.join("#{base_name}-#{uri_hash[0..11]}") + end + end + + def installed? + File.directory?(install_path) + end end end end diff --git a/spec/plugins/source.rb b/spec/plugins/source.rb index 4d1b26f9aef..8285133ab91 100644 --- a/spec/plugins/source.rb +++ b/spec/plugins/source.rb @@ -48,7 +48,121 @@ class Cheater < Bundler::Plugin::API end end - context "with a real source plugin" 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 "fileutils" + + class MPath < Bundler::Plugin::API + source "mpath" + + attr_reader :path + + def initialize(opts) + super + + @path = Pathname.new options["uri"] + end + + def fetch_gemfiles + @gemfiles ||= begin + glob = "{,*,*/*}.gemspec" + if installed? + search_path = install_path + else + search_path = path + end + Dir["\#{search_path.to_s}/\#{glob}"].sort_by {|p| -p.split(File::SEPARATOR).size } + end + end + + def install(spec, opts) + mkdir_p(install_path.parent) + FileUtils.cp_r(path, install_path) + + nil + end + end + RUBY + end # build_plugin + end # build_repo + + build_lib "a-path-gem" + + gemfile <<-G + source "file://#{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" + + should_be_installed("a-path-gem 1.0") + end + + it "writes to lock file" do + bundle "install" + + lockfile_should_be <<-G + PLUGIN + remote: #{lib_path("a-path-gem-1.0")} + type: mpath + specs: + a-path-gem (1.0) + + GEM + remote: file:#{gem_repo2}/ + specs: + + PLATFORMS + #{generic_local_platform} + + DEPENDENCIES + a-path-gem! + + BUNDLED WITH + #{Bundler::VERSION} + G + end + + context "with lockfile" do + before do + lockfile <<-G + PLUGIN + remote: #{lib_path("a-path-gem-1.0")} + type: mpath + specs: + a-path-gem (1.0) + + GEM + remote: file:#{gem_repo2}/ + specs: + + PLATFORMS + #{generic_local_platform} + + DEPENDENCIES + a-path-gem! + + BUNDLED WITH + #{Bundler::VERSION} + G + end + + it "installs", :focused do + bundle "install" + + should_be_installed("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|