Skip to content

Commit

Permalink
Add #recurse_submodules_when_cloning? to control cloning behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
bdragon committed Oct 26, 2022
1 parent 0b1f097 commit 41bac21
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 4 deletions.
46 changes: 42 additions & 4 deletions common/lib/dependabot/file_fetchers/base.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require "stringio"
require "dependabot/config"
require "dependabot/dependency_file"
require "dependabot/source"
Expand Down Expand Up @@ -209,6 +210,10 @@ def update_linked_paths(repo, path, commit, github_response)
end
end

def recurse_submodules_when_cloning?
false
end

def client_for_provider
case source.provider
when "github" then github_client
Expand Down Expand Up @@ -562,6 +567,10 @@ def _linked_dir_for(path)
max_by(&:length)
end

# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/PerceivedComplexity
# rubocop:disable Metrics/BlockLength
def _clone_repo_contents(target_directory:)
SharedHelpers.with_git_configured(credentials: credentials) do
path = target_directory || File.join("tmp", source.repo)
Expand All @@ -570,25 +579,54 @@ def _clone_repo_contents(target_directory:)
return path if Dir.exist?(File.join(path, ".git"))

FileUtils.mkdir_p(path)
br_opt = " --branch #{source.branch} --single-branch" if source.branch

clone_options = StringIO.new
clone_options << "--no-tags --depth 1"
clone_options << if recurse_submodules_when_cloning?
" --recurse-submodules --shallow-submodules"
else
" --no-recurse-submodules"
end
clone_options << " --branch #{source.branch} --single-branch" if source.branch
SharedHelpers.run_shell_command(
<<~CMD
git clone --no-tags --no-recurse-submodules --depth 1#{br_opt} #{source.url} #{path}
git clone #{clone_options.string} #{source.url} #{path}
CMD
)

if source.commit
# This code will only be called for testing. Production will never pass a commit
# since Dependabot always wants to use the latest commit on a branch.
Dir.chdir(path) do
fetch_options = StringIO.new
fetch_options << "--depth 1"
fetch_options << if recurse_submodules_when_cloning?
" --recurse-submodules=on-demand"
else
" --no-recurse-submodules"
end
# Need to fetch the commit due to the --depth 1 above.
SharedHelpers.run_shell_command("git fetch --depth 1 origin #{source.commit}")
SharedHelpers.run_shell_command("git fetch #{fetch_options.string} origin #{source.commit}")

reset_options = StringIO.new
reset_options << "--hard"
reset_options << if recurse_submodules_when_cloning?
" --recurse-submodules"
else
" --no-recurse-submodules"
end

This comment has been minimized.

Copy link
@jakecoffman

jakecoffman Oct 27, 2022

Member

Nice!

# Set HEAD to this commit so later calls so git reset HEAD will work.
SharedHelpers.run_shell_command("git reset --hard #{source.commit}")
SharedHelpers.run_shell_command("git reset #{reset_options.string} #{source.commit}")
end
end

path
end
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/PerceivedComplexity
# rubocop:enable Metrics/BlockLength
end
end
end
Expand Down
94 changes: 94 additions & 0 deletions common/spec/dependabot/file_fetchers/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require "dependabot/source"
require "dependabot/file_fetchers/base"
require "dependabot/clients/codecommit"
require "dependabot/shared_helpers"

RSpec.describe Dependabot::FileFetchers::Base do
let(:source) do
Expand Down Expand Up @@ -1555,4 +1556,97 @@ def fetch_files
end
end
end

context "with submodules" do
let(:repo) { "dependabot-fixtures/go-modules-app-with-git-submodules" }
let(:repo_contents_path) { Dir.mktmpdir }
let(:submodule_contents_path) { File.join(repo_contents_path, "examplelib") }

before do
allow(Dependabot::SharedHelpers).
to receive(:run_shell_command).and_call_original
end

after { FileUtils.rm_rf(repo_contents_path) }

describe "#clone_repo_contents" do
it "does not clone submodules by default" do
file_fetcher_instance.clone_repo_contents

expect(Dependabot::SharedHelpers).
to have_received(:run_shell_command).with(
/\Agit clone .* --no-recurse-submodules/
)
expect(`ls -1 #{submodule_contents_path}`.split).to_not include("go.mod")
end

context "with a source commit" do
let(:source_commit) { "5c7e92a4860382fd31336872f0fe79a848669c4d" }

it "does not fetch/reset submodules by default" do
file_fetcher_instance.clone_repo_contents

expect(Dependabot::SharedHelpers).
to have_received(:run_shell_command).with(
/\Agit fetch .* --no-recurse-submodules/
)
expect(Dependabot::SharedHelpers).
to have_received(:run_shell_command).with(
/\Agit reset .* --no-recurse-submodules/
)
end
end

context "when #recurse_submodules_when_cloning? returns true" do
let(:child_class) do
Class.new(described_class) do
def self.required_files_in?(filenames)
filenames.include?("go.mod")
end

def self.required_files_message
"Repo must contain a go.mod."
end

private

def fetch_files
[fetch_file_from_host("go.mod")]
end

def recurse_submodules_when_cloning?
true
end
end
end

it "clones submodules" do
file_fetcher_instance.clone_repo_contents

expect(Dependabot::SharedHelpers).
to have_received(:run_shell_command).with(
/\Agit clone .* --recurse-submodules --shallow-submodules/
)
expect(`ls -1 #{submodule_contents_path}`.split).to include("go.mod")
end

context "with a source commit" do
let(:source_commit) { "5c7e92a4860382fd31336872f0fe79a848669c4d" }

it "fetches/resets submodules if necessary" do
file_fetcher_instance.clone_repo_contents

expect(Dependabot::SharedHelpers).
to have_received(:run_shell_command).with(
/\Agit fetch .* --recurse-submodules=on-demand/
)
expect(Dependabot::SharedHelpers).
to have_received(:run_shell_command).with(
/\Agit reset .* --recurse-submodules/
)
end
end
end
end
end
end

0 comments on commit 41bac21

Please sign in to comment.