ansible-galaxy: Clone git collections using shallow clones (#75722)

* ansible-galaxy: Clone git collections using shallow clones

This ensures the collection obtained via git url is a result of a
shallow git clone (git clone --depth=1). The git history of the
collection is not used by ansible, and as such, cloning the entire
history of the repo is unnecessary.

Signed-off-by: Tomas Babej <tomas@tbabej.com>

* ansible-galaxy: Only perform shallow clones on non-versioned git urls

In general, the version can be anything we can checkout (branch, tag,
but also a commit hash). In particular for commit hashes we cannot
perform a shallow clone.

Err on the safe side and only perform shallow clones for non-versioned
git urls (cloning HEAD).

* galaxy-install: Make shallow cloning compatible with older Python versions

Signed-off-by: Tomas Babej <tomas@tbabej.com>

* Pass args as a tuple

Add tests for the git command created from different repo and version combinations

* changelog

Co-authored-by: Tomas Babej <tomas@tbabej.com>
pull/75755/head
Sloane Hertel 3 years ago committed by GitHub
parent 724800cd3f
commit 7ecc227488
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
minor_changes:
- >-
ansible-galaxy - Installing a collection from a git repository
without specifying a version (or using the version ``HEAD``)
will clone the repository using --depth=1.

@ -347,8 +347,14 @@ def _extract_collection_from_git(repo_url, coll_ver, b_path):
dir=b_path,
prefix=to_bytes(name, errors='surrogate_or_strict'),
) # type: bytes
git_clone_cmd = 'git', 'clone', git_url, to_text(b_checkout_path)
# FIXME: '--depth', '1', '--branch', version
# Perform a shallow clone if simply cloning HEAD
if version == 'HEAD':
git_clone_cmd = 'git', 'clone', '--depth=1', git_url, to_text(b_checkout_path)
else:
git_clone_cmd = 'git', 'clone', git_url, to_text(b_checkout_path)
# FIXME: '--branch', version
try:
subprocess.check_call(git_clone_cmd)
except subprocess.CalledProcessError as proc_err:

@ -171,6 +171,63 @@ def galaxy_server():
return galaxy_api
@pytest.mark.parametrize(
'url,version,trailing_slash',
[
('https://github.com/org/repo', 'commitish', False),
('https://github.com/org/repo,commitish', None, False),
('https://github.com/org/repo/,commitish', None, True),
('https://github.com/org/repo#,commitish', None, False),
]
)
def test_concrete_artifact_manager_scm_cmd(url, version, trailing_slash, monkeypatch):
mock_subprocess_check_call = MagicMock()
monkeypatch.setattr(collection.concrete_artifact_manager.subprocess, 'check_call', mock_subprocess_check_call)
mock_mkdtemp = MagicMock(return_value='')
monkeypatch.setattr(collection.concrete_artifact_manager, 'mkdtemp', mock_mkdtemp)
collection.concrete_artifact_manager._extract_collection_from_git(url, version, b'path')
assert mock_subprocess_check_call.call_count == 2
repo = 'https://github.com/org/repo'
if trailing_slash:
repo += '/'
clone_cmd = ('git', 'clone', repo, '')
assert mock_subprocess_check_call.call_args_list[0].args[0] == clone_cmd
assert mock_subprocess_check_call.call_args_list[1].args[0] == ('git', 'checkout', 'commitish')
@pytest.mark.parametrize(
'url,version,trailing_slash',
[
('https://github.com/org/repo', 'HEAD', False),
('https://github.com/org/repo,HEAD', None, False),
('https://github.com/org/repo/,HEAD', None, True),
('https://github.com/org/repo#,HEAD', None, False),
('https://github.com/org/repo', None, False),
]
)
def test_concrete_artifact_manager_scm_cmd_shallow(url, version, trailing_slash, monkeypatch):
mock_subprocess_check_call = MagicMock()
monkeypatch.setattr(collection.concrete_artifact_manager.subprocess, 'check_call', mock_subprocess_check_call)
mock_mkdtemp = MagicMock(return_value='')
monkeypatch.setattr(collection.concrete_artifact_manager, 'mkdtemp', mock_mkdtemp)
collection.concrete_artifact_manager._extract_collection_from_git(url, version, b'path')
assert mock_subprocess_check_call.call_count == 2
repo = 'https://github.com/org/repo'
if trailing_slash:
repo += '/'
shallow_clone_cmd = ('git', 'clone', '--depth=1', repo, '')
assert mock_subprocess_check_call.call_args_list[0].args[0] == shallow_clone_cmd
assert mock_subprocess_check_call.call_args_list[1].args[0] == ('git', 'checkout', 'HEAD')
def test_build_requirement_from_path(collection_artifact):
tmp_path = os.path.join(os.path.split(collection_artifact[1])[0], b'temp')
concrete_artifact_cm = collection.concrete_artifact_manager.ConcreteArtifactsManager(tmp_path, validate_certs=False)

Loading…
Cancel
Save