Skip to content

Commit 24cff33

Browse files
committed
Clone bare repository, fall back to cloning full repository
This updates the `GClone` spec searcher to start by attempting to clone a bare repository. If cloning a bare repository fails, the spec searcher falls back to attempting to clone the full repository. Because Puppetfile supports using commits/SHA1s as refs when installing git modules, puppetfile-resolver needs to support them as well. Cloning bare repositories with a commit/SHA1 fails, so falling back to a full clone ensures that the resolver supports this behavior. The spec searcher could always clone a full repository instead of first attempting to clone a bare repository, but this might dramatically increase the time it takes to clone a module.
1 parent 5a55794 commit 24cff33

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

lib/puppetfile-resolver/spec_searchers/git/gclone.rb

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ module PuppetfileResolver
1212
module SpecSearchers
1313
module Git
1414
module GClone
15+
METADATA_FILE = 'metadata.json'
16+
1517
# @summary clones the remote url and reads the metadata file
1618
# @returns [String] the content of the metadata file
1719
def self.metadata(puppetfile_module, resolver_ui, config)
@@ -25,8 +27,6 @@ def self.metadata(puppetfile_module, resolver_ui, config)
2527
return nil if repo_url.nil?
2628
return nil unless valid_http_url?(repo_url)
2729

28-
metadata_file = 'metadata.json'
29-
3030
ref = puppetfile_module.ref ||
3131
puppetfile_module.tag ||
3232
puppetfile_module.commit ||
@@ -35,7 +35,7 @@ def self.metadata(puppetfile_module, resolver_ui, config)
3535

3636
resolver_ui.debug { "Querying git repository #{repo_url}" }
3737

38-
clone_and_read_file(repo_url, ref, metadata_file, config)
38+
clone_and_read_file(repo_url, ref, config)
3939
end
4040

4141
# @summary clones the git url and reads the file at the given ref
@@ -44,25 +44,37 @@ def self.metadata(puppetfile_module, resolver_ui, config)
4444
# @param ref [String] the git ref, branch, commit, tag
4545
# @param file [String] the file you wish to read
4646
# @returns [String] the content of the file
47-
def self.clone_and_read_file(url, ref, file, config)
47+
def self.clone_and_read_file(url, ref, config)
4848
Dir.mktmpdir(nil, config.clone_dir) do |dir|
49-
clone_cmd = ['git', 'clone', url, dir]
50-
clone_cmd += ['--config', "http.proxy=#{config.proxy}", '--config', "https.proxy=#{config.proxy}"] if config.proxy
49+
clone = ['git', 'clone', url, dir]
50+
clone += ['--config', "http.proxy=#{config.proxy}", '--config', "https.proxy=#{config.proxy}"] if config.proxy
5151

52-
_out, err_out, process = ::PuppetfileResolver::Util.run_command(clone_cmd)
52+
bare_clone = clone + ['--bare', '--depth=1']
53+
bare_clone.push("--branch=#{ref}") unless ref == 'HEAD'
54+
55+
# Try to clone a bare repository. If that fails, fall back to a full clone.
56+
# Cloning might fail because the repo does not exist or is otherwise
57+
# inaccessible, but it can also fail because cloning a bare repository from
58+
# a commit/SHA1 fails. Falling back to a full clone ensures that we support
59+
# commits/SHA1s like Puppetfile does.
60+
_stdout, _stderr, process = ::PuppetfileResolver::Util.run_command(bare_clone)
5361

5462
unless process.success?
55-
msg = if config.proxy
56-
"Cloning #{url} with proxy #{config.proxy} failed: #{err_out}"
57-
else
58-
"Cloning #{url} failed: #{err_out}"
59-
end
60-
raise msg
63+
_stdout, stderr, process = ::PuppetfileResolver::Util.run_command(clone)
64+
65+
unless process.success?
66+
msg = if config.proxy
67+
"Cloning #{url} with proxy #{config.proxy} failed: #{stderr}"
68+
else
69+
"Cloning #{url} failed: #{stderr}"
70+
end
71+
raise msg
72+
end
6173
end
6274

6375
Dir.chdir(dir) do
64-
content, err_out, process = ::PuppetfileResolver::Util.run_command(['git', 'show', "#{ref}:#{file}"])
65-
raise 'InvalidContent' unless process.success? && content.length > 2
76+
content, stderr, process = ::PuppetfileResolver::Util.run_command(['git', 'show', "#{ref}:#{METADATA_FILE}"])
77+
raise "Could not find #{METADATA_FILE} for ref #{ref} at #{url}: #{stderr}" unless process.success?
6678
return content
6779
end
6880
end

spec/unit/puppetfile-resolver/spec_searchers/git/gclone_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@
4444
expect(JSON.parse(content)['name']).to eq('puppetlabs-powershell')
4545
end
4646
end
47+
48+
context 'with invalid ref' do
49+
let(:puppetfile_module) do
50+
PuppetfileModule.new(remote: url, ref: '8f7d5ea3ef49dadc5e166d5d802d091abc4b02bc')
51+
end
52+
53+
it 'errors gracefully' do
54+
expect { subject.metadata(puppetfile_module, Logger.new(STDERR), config) }.to raise_error(
55+
/Could not find metadata\.json for ref .* at .*/
56+
)
57+
end
58+
end
4759
end
4860

4961
context 'invalid url' do

0 commit comments

Comments
 (0)