aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bundler/source
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2022-12-09 14:45:51 +0900
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2022-12-09 16:36:22 +0900
commita4e14b9d9d58391fb7d7a10be8d883690860373b (patch)
tree08f9c871583bd0a0d98b9cac3389ad52631400be /lib/bundler/source
parentd928ebacb23639cbf3f28201304f0451e5bd45a7 (diff)
downloadruby-a4e14b9d9d58391fb7d7a10be8d883690860373b.tar.gz
Merge RubyGems/Bundler master
Pick from https://github.com/rubygems/rubygems/commit/823c776d951f3c35094611473ec77f94e8bf6610
Diffstat (limited to 'lib/bundler/source')
-rw-r--r--lib/bundler/source/git.rb16
-rw-r--r--lib/bundler/source/git/git_proxy.rb167
2 files changed, 141 insertions, 42 deletions
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index fd34edffb7..745ae05c5c 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -72,7 +72,7 @@ module Bundler
elsif ref
ref
else
- git_proxy.branch
+ current_branch
end
rev = "at #{at}@#{shortref_for_display(revision)}"
@@ -126,7 +126,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"
@@ -141,11 +141,11 @@ 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
@@ -228,6 +228,10 @@ module Bundler
git_proxy.revision
end
+ def current_branch
+ git_proxy.current_branch
+ end
+
def allow_git_ops?
@allow_remote || @allow_cached
end
@@ -313,7 +317,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
diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb
index 745a7fe118..5468536f86 100644
--- a/lib/bundler/source/git/git_proxy.rb
+++ b/lib/bundler/source/git/git_proxy.rb
@@ -47,13 +47,15 @@ module Bundler
# All actions required by the Git source is encapsulated in this
# object.
class GitProxy
- attr_accessor :path, :uri, :ref
+ attr_accessor :path, :uri, :branch, :tag, :ref
attr_writer :revision
- def initialize(path, uri, ref, revision = nil, git = nil)
+ def initialize(path, uri, options = {}, revision = nil, git = nil)
@path = path
@uri = uri
- @ref = ref
+ @branch = options["branch"]
+ @tag = options["tag"]
+ @ref = options["ref"]
@revision = revision
@git = git
end
@@ -62,8 +64,8 @@ module Bundler
@revision ||= find_local_revision
end
- def branch
- @branch ||= allowed_with_path do
+ def current_branch
+ @current_branch ||= allowed_with_path do
git("rev-parse", "--abbrev-ref", "HEAD", :dir => path).strip
end
end
@@ -76,36 +78,33 @@ module Bundler
end
def version
- git("--version").match(/(git version\s*)?((\.?\d+)+).*/)[2]
+ @version ||= full_version.match(/((\.?\d+)+).*/)[1]
end
def full_version
- git("--version").sub("git version", "").strip
+ @full_version ||= git("--version").sub(/git version\s*/, "").strip
end
def checkout
- return if path.exist? && has_revision_cached?
- extra_ref = "#{ref}:#{ref}" if ref && ref.start_with?("refs/")
+ return if has_revision_cached?
- Bundler.ui.info "Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"
-
- configured_uri = configured_uri_for(uri).to_s
+ Bundler.ui.info "Fetching #{credential_filtered_uri}"
unless path.exist?
SharedHelpers.filesystem_access(path.dirname) do |p|
FileUtils.mkdir_p(p)
end
- git_retry "clone", "--bare", "--no-hardlinks", "--quiet", "--", configured_uri, path.to_s
+ git_retry "clone", "--bare", "--no-hardlinks", "--quiet", *extra_clone_args, "--", configured_uri, path.to_s
return unless extra_ref
end
- with_path do
- git_retry(*["fetch", "--force", "--quiet", "--tags", "--", configured_uri, "refs/heads/*:refs/heads/*", extra_ref].compact, :dir => path)
- end
+ fetch_args = extra_fetch_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)
end
def copy_to(destination, submodules = false)
- # method 1
unless File.exist?(destination.join(".git"))
begin
SharedHelpers.filesystem_access(destination.dirname) do |p|
@@ -114,7 +113,7 @@ module Bundler
SharedHelpers.filesystem_access(destination) do |p|
FileUtils.rm_rf(p)
end
- git_retry "clone", "--no-checkout", "--quiet", path.to_s, destination.to_s
+ git "clone", "--no-checkout", "--quiet", path.to_s, destination.to_s
File.chmod(((File.stat(destination).mode | 0o777) & ~File.umask), destination)
rescue Errno::EEXIST => e
file_path = e.message[%r{.*?((?:[a-zA-Z]:)?/.*)}, 1]
@@ -123,14 +122,10 @@ module Bundler
"this file and try again."
end
end
- # method 2
- git_retry "fetch", "--force", "--quiet", "--tags", path.to_s, :dir => destination
- begin
- git "reset", "--hard", @revision, :dir => destination
- rescue GitCommandError => e
- raise MissingGitRevisionError.new(e.command, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
- end
+ git(*["fetch", "--force", "--quiet", *extra_fetch_args, path.to_s, revision_refspec].compact, :dir => destination)
+
+ git "reset", "--hard", @revision, :dir => destination
if submodules
git_retry "submodule", "update", "--init", "--recursive", :dir => destination
@@ -142,6 +137,69 @@ module Bundler
private
+ def extra_ref
+ return false if not_pinned?
+ return true unless full_clone?
+
+ ref.start_with?("refs/")
+ end
+
+ def depth
+ return @depth if defined?(@depth)
+
+ @depth = if legacy_locked_revision? || !supports_fetching_unreachable_refs?
+ nil
+ elsif not_pinned?
+ 1
+ elsif ref.include?("~")
+ parsed_depth = ref.split("~").last
+ parsed_depth.to_i + 1
+ elsif abbreviated_ref?
+ nil
+ else
+ 1
+ end
+ end
+
+ def refspec
+ if fully_qualified_ref
+ "#{fully_qualified_ref}:#{fully_qualified_ref}"
+ elsif ref.include?("~")
+ parsed_ref = ref.split("~").first
+ "#{parsed_ref}:#{parsed_ref}"
+ elsif ref.start_with?("refs/")
+ "#{ref}:#{ref}"
+ elsif abbreviated_ref?
+ nil
+ else
+ ref
+ end
+ end
+
+ def fully_qualified_ref
+ return @fully_qualified_ref if defined?(@fully_qualified_ref)
+
+ @fully_qualified_ref = if branch
+ "refs/heads/#{branch}"
+ elsif tag
+ "refs/tags/#{tag}"
+ elsif ref.nil?
+ "refs/heads/#{current_branch}"
+ end
+ end
+
+ def not_pinned?
+ branch || tag || ref.nil?
+ end
+
+ def abbreviated_ref?
+ ref =~ /\A\h+\z/ && ref !~ /\A\h{40}\z/
+ end
+
+ def legacy_locked_revision?
+ !@revision.nil? && @revision =~ /\A\h{7}\z/
+ end
+
def git_null(*command, dir: nil)
check_allowed(command)
@@ -175,37 +233,40 @@ module Bundler
end
def has_revision_cached?
- return unless @revision
- with_path { git("cat-file", "-e", @revision, :dir => path) }
+ return unless @revision && path.exist?
+ git("cat-file", "-e", @revision, :dir => path)
true
rescue GitError
false
end
- def remove_cache
- FileUtils.rm_rf(path)
- end
-
def find_local_revision
allowed_with_path do
- git("rev-parse", "--verify", ref || "HEAD", :dir => path).strip
+ git("rev-parse", "--verify", branch || tag || ref || "HEAD", :dir => path).strip
end
rescue GitCommandError => e
- raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
+ raise MissingGitRevisionError.new(e.command, path, branch || tag || ref, credential_filtered_uri)
end
- # Adds credentials to the URI as Fetcher#configured_uri_for does
- def configured_uri_for(uri)
+ # Adds credentials to the URI
+ def configured_uri
if /https?:/ =~ uri
remote = Bundler::URI(uri)
config_auth = Bundler.settings[remote.to_s] || Bundler.settings[remote.host]
remote.userinfo ||= config_auth
remote.to_s
+ elsif File.exist?(uri)
+ "file://#{uri}"
else
- uri
+ uri.to_s
end
end
+ # Removes credentials from the URI
+ def credential_filtered_uri
+ URICredentialsFilter.credential_filtered_uri(uri)
+ end
+
def allow?
allowed = @git ? @git.allow_git_ops? : true
@@ -254,9 +315,43 @@ module Bundler
end
end
+ def extra_clone_args
+ return [] if full_clone?
+
+ args = ["--depth", depth.to_s, "--single-branch"]
+ args.unshift("--no-tags") if supports_cloning_with_no_tags?
+
+ args += ["--branch", branch || tag] if branch || tag
+ args
+ end
+
+ def extra_fetch_args
+ return [] if full_clone?
+
+ ["--depth", depth.to_s]
+ end
+
+ def revision_refspec
+ return if legacy_locked_revision?
+
+ revision
+ end
+
+ def full_clone?
+ depth.nil?
+ end
+
def supports_minus_c?
@supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5")
end
+
+ def supports_fetching_unreachable_refs?
+ @supports_fetching_unreachable_refs ||= Gem::Version.new(version) >= Gem::Version.new("2.5.0")
+ end
+
+ def supports_cloning_with_no_tags?
+ @supports_cloning_with_no_tags ||= Gem::Version.new(version) >= Gem::Version.new("2.14.0-rc0")
+ end
end
end
end