diff options
Diffstat (limited to 'lib/bundler/source/git.rb')
-rw-r--r-- | lib/bundler/source/git.rb | 128 |
1 files changed, 85 insertions, 43 deletions
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb index fb13ca0578..198e335bb6 100644 --- a/lib/bundler/source/git.rb +++ b/lib/bundler/source/git.rb @@ -11,6 +11,7 @@ module Bundler def initialize(options) @options = options + @checksum_store = Checksum::Store.new @glob = options["glob"] || DEFAULT_GLOB @allow_cached = false @@ -19,7 +20,7 @@ module Bundler # Stringify options that could be set as symbols %w[ref branch tag revision].each {|k| options[k] = options[k].to_s if options[k] } - @uri = options["uri"] || "" + @uri = URINormalizer.normalize_suffix(options["uri"] || "", trailing_slash: false) @safe_uri = URICredentialsFilter.credential_filtered_uri(@uri) @branch = options["branch"] @ref = options["ref"] || options["branch"] || options["tag"] @@ -42,10 +43,18 @@ module Bundler %w[ref branch tag submodules].each do |opt| out << " #{opt}: #{options[opt]}\n" if options[opt] end - out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB + out << " glob: #{@glob}\n" unless default_glob? out << " specs:\n" end + def to_gemfile + specifiers = %w[ref branch tag submodules glob].map do |opt| + "#{opt}: #{options[opt]}" if options[opt] + end + + uri_with_specifiers(specifiers) + end + def hash [self.class, uri, ref, branch, name, version, glob, submodules].hash end @@ -59,28 +68,40 @@ module Bundler alias_method :==, :eql? + def include?(other) + other.is_a?(Git) && uri == other.uri && + name == other.name && + glob == other.glob && + submodules == other.submodules + end + def to_s begin - at = if local? - path - elsif user_ref = options["ref"] - if ref =~ /\A[a-z0-9]{4,}\z/i - shortref_for_display(user_ref) - else - user_ref - end - elsif ref - ref - else - git_proxy.branch - end + at = humanized_ref || current_branch - rev = " (at #{at}@#{shortref_for_display(revision)})" + rev = "at #{at}@#{shortref_for_display(revision)}" rescue GitError "" end - "#{@safe_uri}#{rev}" + uri_with_specifiers([rev, glob_for_display]) + end + + def identifier + uri_with_specifiers([humanized_ref, cached_revision, glob_for_display]) + end + + def uri_with_specifiers(specifiers) + specifiers.compact! + + suffix = + if specifiers.any? + " (#{specifiers.join(", ")})" + else + "" + end + + "#{@safe_uri}#{suffix}" end def name @@ -94,13 +115,7 @@ module Bundler @install_path ||= begin git_scope = "#{base_name}-#{shortref_for_path(revision)}" - path = Bundler.install_path.join(git_scope) - - if !path.exist? && Bundler.requires_sudo? - Bundler.user_bundle_path.join(Bundler.ruby_scope).join(git_scope) - else - path - end + Bundler.install_path.join(git_scope) end end @@ -124,7 +139,7 @@ module Bundler path = Pathname.new(path) path = path.expand_path(Bundler.root) unless path.relative? - unless options["branch"] || Bundler.settings[:disable_local_branch_check] + unless branch || Bundler.settings[:disable_local_branch_check] raise GitError, "Cannot use local override for #{name} at #{path} because " \ ":branch is not specified in Gemfile. Specify a branch or run " \ "`bundle config unset local.#{override_for(original_path)}` to remove the local override" @@ -139,14 +154,14 @@ module Bundler # Create a new git proxy without the cached revision # so the Gemfile.lock always picks up the new revision. - @git_proxy = GitProxy.new(path, uri, ref) + @git_proxy = GitProxy.new(path, uri, options) - if git_proxy.branch != options["branch"] && !Bundler.settings[:disable_local_branch_check] + if current_branch != branch && !Bundler.settings[:disable_local_branch_check] raise GitError, "Local override for #{name} at #{path} is using branch " \ - "#{git_proxy.branch} but Gemfile specifies #{options["branch"]}" + "#{current_branch} but Gemfile specifies #{branch}" 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) raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \ @@ -171,9 +186,10 @@ module Bundler end def install(spec, options = {}) + return if Bundler.settings[:no_install] force = options[:force] - print_using_message "Using #{version_message(spec)} from #{self}" + print_using_message "Using #{version_message(spec, options[:previous_spec])} from #{self}" if (requires_checkout? && !@copied) || force Bundler.ui.debug " * Checking out revision: #{ref}" @@ -182,7 +198,7 @@ module Bundler @copied = true end - generate_bin_options = { :disable_extensions => !Bundler.rubygems.spec_missing_extensions?(spec), :build_args => options[:build_args] } + generate_bin_options = { disable_extensions: !Bundler.rubygems.spec_missing_extensions?(spec), build_args: options[:build_args] } generate_bin(spec, generate_bin_options) requires_checkout? ? spec.post_install_message : nil @@ -211,13 +227,11 @@ module Bundler # across different projects, this cache will be shared. # When using local git repos, this is set to the local repo. def cache_path - @cache_path ||= begin - if Bundler.requires_sudo? || Bundler.feature_flag.global_gem_cache? - Bundler.user_cache - else - Bundler.bundle_path.join("cache", "bundler") - end.join("git", git_scope) - end + @cache_path ||= if Bundler.feature_flag.global_gem_cache? + Bundler.user_cache + else + Bundler.bundle_path.join("cache", "bundler") + end.join("git", git_scope) end def app_cache_dirname @@ -228,6 +242,10 @@ module Bundler git_proxy.revision end + def current_branch + git_proxy.current_branch + end + def allow_git_ops? @allow_remote || @allow_cached end @@ -238,6 +256,20 @@ module Bundler private + def humanized_ref + if local? + path + elsif user_ref = options["ref"] + if /\A[a-z0-9]{4,}\z/i.match?(ref) + shortref_for_display(user_ref) + else + user_ref + end + elsif ref + ref + end + end + def serialize_gemspecs_in(destination) destination = destination.expand_path(Bundler.root) if destination.relative? Dir["#{destination}/#{@glob}"].each do |spec_path| @@ -282,16 +314,26 @@ module Bundler ref[0..11] end + def glob_for_display + default_glob? ? nil : "glob: #{@glob}" + end + + def default_glob? + @glob == DEFAULT_GLOB + end + def uri_hash - if uri =~ %r{^\w+://(\w+@)?} + if %r{^\w+://(\w+@)?}.match?(uri) # Downcase the domain component of the URI # and strip off a trailing slash, if one is present - input = Bundler::URI.parse(uri).normalize.to_s.sub(%r{/$}, "") + input = Gem::URI.parse(uri).normalize.to_s.sub(%r{/$}, "") else # If there is no URI scheme, assume it is an ssh/git URI input = uri end - SharedHelpers.digest(:SHA1).hexdigest(input) + # We use SHA1 here for historical reason and to preserve backward compatibility. + # But a transition to a simpler mangling algorithm would be welcome. + Bundler::Digest.sha1(input) end def cached_revision @@ -303,7 +345,7 @@ module Bundler end def git_proxy - @git_proxy ||= GitProxy.new(cache_path, uri, ref, cached_revision, self) + @git_proxy ||= GitProxy.new(cache_path, uri, options, cached_revision, self) end def fetch @@ -318,7 +360,7 @@ module Bundler def load_gemspec(file) stub = Gem::StubSpecification.gemspec_stub(file, install_path.parent, install_path.parent) - stub.full_gem_path = Pathname.new(file).dirname.expand_path(root).to_s.tap{|x| x.untaint if RUBY_VERSION < "2.7" } + stub.full_gem_path = Pathname.new(file).dirname.expand_path(root).to_s StubSpecification.from_stub(stub) end |