From 9cf802a07aded8cccb35e2d19fe3b0939cda65fc Mon Sep 17 00:00:00 2001 From: Costa Shapiro Date: Tue, 11 Nov 2025 23:19:58 +0200 Subject: [PATCH] fixes #9001 - dumb http git support for bundler update fixed... ...by a little code duplication; specs are somewhat improved though --- bundler/lib/bundler/source/git/git_proxy.rb | 8 +++ .../spec/bundler/source/git/git_proxy_spec.rb | 67 ++++++++++++------- 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/bundler/lib/bundler/source/git/git_proxy.rb b/bundler/lib/bundler/source/git/git_proxy.rb index 02ec121abeca..d5575cc81cfa 100644 --- a/bundler/lib/bundler/source/git/git_proxy.rb +++ b/bundler/lib/bundler/source/git/git_proxy.rb @@ -166,6 +166,14 @@ def git_remote_fetch(args) if err.include?("couldn't find remote ref") || err.include?("not our ref") raise MissingGitRevisionError.new(command_with_no_credentials, path, commit || explicit_ref, credential_filtered_uri) else + idx = command.index("--depth") + if idx + command.delete_at(idx) + command.delete_at(idx) + command_with_no_credentials = check_allowed(command) + + err += "Retrying without --depth argument." + end raise GitCommandError.new(command_with_no_credentials, path, err) end end diff --git a/bundler/spec/bundler/source/git/git_proxy_spec.rb b/bundler/spec/bundler/source/git/git_proxy_spec.rb index b2b7ab5c5400..f75b2c674f3d 100644 --- a/bundler/spec/bundler/source/git/git_proxy_spec.rb +++ b/bundler/spec/bundler/source/git/git_proxy_spec.rb @@ -9,10 +9,17 @@ let(:options) { { "ref" => ref, "branch" => branch, "tag" => tag }.compact } let(:revision) { nil } let(:git_source) { nil } - let(:clone_result) { double(Process::Status, success?: true) } + let(:success_result) { double(Process::Status, success?: true) } let(:base_clone_args) { ["clone", "--bare", "--no-hardlinks", "--quiet", "--no-tags", "--depth", "1", "--single-branch"] } + let(:failure_result) { double(Process::Status, success?: false) } + let(:base_fetch_args) { ["fetch", "--force", "--quiet", "--no-tags", "--depth", "1"] } subject(:git_proxy) { described_class.new(path, uri, options, revision, git_source) } + def args_without_depth(args) + depth_arg_i = args.index("--depth") + args[0..(depth_arg_i - 1)] + args[(depth_arg_i + 2)..-1] + end + context "with explicit ref" do context "with branch only" do let(:branch) { "main" } @@ -64,7 +71,7 @@ it "adds username and password to URI" do Bundler.settings.temporary(uri => "u:p") do allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") - expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/ruby/rubygems.git", path.to_s], nil).and_return(["", "", clone_result]) + expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/ruby/rubygems.git", path.to_s], nil).and_return(["", "", success_result]) subject.checkout end end @@ -72,7 +79,7 @@ it "adds username and password to URI for host" do Bundler.settings.temporary("github.com" => "u:p") do allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") - expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/ruby/rubygems.git", path.to_s], nil).and_return(["", "", clone_result]) + expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/ruby/rubygems.git", path.to_s], nil).and_return(["", "", success_result]) subject.checkout end end @@ -80,7 +87,7 @@ it "does not add username and password to mismatched URI" do Bundler.settings.temporary("https://u:p@github.com/ruby/rubygems-mismatch.git" => "u:p") do allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") - expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "", clone_result]) + expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "", success_result]) subject.checkout end end @@ -90,7 +97,7 @@ original = "https://orig:info@github.com/ruby/rubygems.git" git_proxy = described_class.new(Pathname("path"), original, options) allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") - expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", original, path.to_s], nil).and_return(["", "", clone_result]) + expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", original, path.to_s], nil).and_return(["", "", success_result]) git_proxy.checkout end end @@ -198,20 +205,6 @@ expect(Pathname.new(bundled_app("canary"))).not_to exist end - context "URI is HTTP" do - let(:uri) { "http://github.com/ruby/rubygems.git" } - let(:without_depth_arguments) { ["clone", "--bare", "--no-hardlinks", "--quiet", "--no-tags", "--single-branch"] } - let(:fail_clone_result) { double(Process::Status, success?: false) } - - it "retries without --depth when git url is http and fails" do - allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") - allow(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "dumb http transport does not support shallow capabilities", fail_clone_result]) - expect(git_proxy).to receive(:capture).with([*without_depth_arguments, "--", uri, path.to_s], nil).and_return(["", "", clone_result]) - - subject.checkout - end - end - describe "#installed_to?" do let(:destination) { "install/dir" } let(:destination_dir_exists) { true } @@ -261,9 +254,21 @@ it "clones the repository" do allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") - expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "", clone_result]) + expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "", success_result]) subject.checkout end + + context "URI is HTTP" do + let(:uri) { "http://git/rubygems/.git" } + + it "retries without --depth when git url is http and fails" do + allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") + expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "dumb http transport does not support shallow capabilities", failure_result]) + expect(git_proxy).to receive(:capture).with([*args_without_depth(base_clone_args), "--", uri, path.to_s], nil).and_return(["", "", success_result]) + + subject.checkout + end + end end context "when the repository is cloned" do @@ -286,7 +291,7 @@ it "fetches the specific revision" do allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") expect(git_proxy).to receive(:git).with("cat-file", "-e", revision, dir: path).and_raise(Bundler::GitError) - expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--depth", "1", "--", uri, "#{revision}:refs/#{revision}-sha"], path).and_return(["", "", clone_result]) + expect(git_proxy).to receive(:capture).with([*base_fetch_args, "--", uri, "#{revision}:refs/#{revision}-sha"], path).and_return(["", "", success_result]) subject.checkout end end @@ -297,7 +302,7 @@ parsed_revision = Digest::SHA1.hexdigest("ruby") allow(git_proxy).to receive(:git_local).with("rev-parse", "--abbrev-ref", "HEAD", dir: path).and_return(parsed_revision) allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") - expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--depth", "1", "--", uri, "refs/heads/#{parsed_revision}:refs/heads/#{parsed_revision}"], path).and_return(["", "", clone_result]) + expect(git_proxy).to receive(:capture).with([*base_fetch_args, "--", uri, "refs/heads/#{parsed_revision}:refs/heads/#{parsed_revision}"], path).and_return(["", "", success_result]) subject.checkout end end @@ -317,7 +322,7 @@ it "fetches the specific revision" do allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") expect(git_proxy).to receive(:git).with("cat-file", "-e", ref, dir: path).and_raise(Bundler::GitError) - expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--depth", "1", "--", uri, "#{ref}:refs/#{ref}-sha"], path).and_return(["", "", clone_result]) + expect(git_proxy).to receive(:capture).with([*base_fetch_args, "--", uri, "#{ref}:refs/#{ref}-sha"], path).and_return(["", "", success_result]) subject.checkout end end @@ -328,7 +333,21 @@ it "fetches all revisions" do allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") - expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--", uri, "refs/*:refs/*"], path).and_return(["", "", clone_result]) + expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--", uri, "refs/*:refs/*"], path).and_return(["", "", success_result]) + subject.checkout + end + end + + context "URI is HTTP" do + let(:uri) { "http://git/rubygems/.git" } + + it "retries without --depth when git url is http and fails" do + allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0") + parsed_revision = Digest::SHA1.hexdigest("ruby") + allow(git_proxy).to receive(:git_local).with("rev-parse", "--abbrev-ref", "HEAD", dir: path).and_return(parsed_revision) + expect(git_proxy).to receive(:capture).with([*base_fetch_args, "--", uri, "refs/heads/#{parsed_revision}:refs/heads/#{parsed_revision}"], path).and_return(["", "dumb http transport does not support shallow capabilities", failure_result]) + expect(git_proxy).to receive(:capture).with([*args_without_depth(base_fetch_args), "--", uri, "refs/heads/#{parsed_revision}:refs/heads/#{parsed_revision}"], path).and_return(["", "", success_result]) + subject.checkout end end