Commit 5b60b88e authored by Ayush Tiwari's avatar Ayush Tiwari

gitclone: Add support for cloning submodules by default

Also, add functionality to update the submodules when trying to
fetch the main repo and the reference for submodule at the main
repo has been updated.
parent 5e6da988
......@@ -121,7 +121,7 @@ try to redownload resource with wrong md5sum.
slapos.recipe.build:gitclone
==============================
Checkout a git repository.
Checkout a git repository and its submodules by default.
Supports slapos.libnetworkcache if present, and if boolean 'use-cache' option
is true.
......@@ -391,7 +391,7 @@ Then, when update occurs, nothing is done::
Unable to update:
Traceback (most recent call last):
...
...CalledProcessError: Command '['git', 'fetch', '--all']' returned non-zero exit status 1
...CalledProcessError: Command '['git', 'fetch', '--recurse-submodules', '--all']' returned non-zero exit status 1
<BLANKLINE>
...
fatal: unable to access 'http://git.erp5.org/repos/nowhere/': The requested URL returned error: 500
......@@ -450,6 +450,21 @@ boolean option::
repository = https://example.net/example.git/
ignore-ssl-certificate = true
Ignore cloning submodules
~~~~~~~~~~~~~~~~~~~~~~~~~
By default, cloning the repository will clone its submodules also. You can force
git to ignore cloinig submodules by defining `ignore-cloning-submodules` boolean
option to 'true'::
[buildout]
parts = git-clone
[git-clone]
recipe = slapos.recipe.build:gitclone
repository = https://lab.nexedi.com/tiwariayush/test_erp5
ignore-cloning-submodules = true
Other options
~~~~~~~~~~~~~
......
......@@ -8,6 +8,7 @@ import stat
import tempfile
import unittest
import zc.buildout.testing
from subprocess import check_call, check_output
from slapos.recipe.gitclone import GIT_CLONE_ERROR_MESSAGE, \
GIT_CLONE_CACHE_ERROR_MESSAGE
......@@ -15,6 +16,8 @@ optionflags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE)
GIT_REPOSITORY = 'https://lab.nexedi.com/nexedi/slapos.recipe.build.git'
BAD_GIT_REPOSITORY = 'http://git.erp5.org/repos/nowhere'
GIT_REPOSITORY_WITH_SUBMODULES = 'https://lab.nexedi.com/tiwariayush/test_erp5'
GIT_SUBMODULE_REPOSITORY = 'https://lab.nexedi.com/tiwariayush/test_erp5_submodule'
REVISION = '2566127'
def setUp(test):
......@@ -117,7 +120,6 @@ class GitCloneNonInformativeTests(unittest.TestCase):
# Check git clone parameters
_ = self.assertIn if ignore_ssl_certificate else self.assertNotIn
_("--config", check_call_parameter_list[0][0])
_("http.sslVerify=false", check_call_parameter_list[0][0])
# Restore original check_call method
......@@ -126,6 +128,69 @@ class GitCloneNonInformativeTests(unittest.TestCase):
def test_ignore_ssl_certificate_false(self):
self.test_ignore_ssl_certificate(ignore_ssl_certificate=False)
def test_clone_submodules_by_default(self, ignore_cloning_submodules=False):
recipe = self.makeGitCloneRecipe(
{'repository': GIT_REPOSITORY_WITH_SUBMODULES,
'ignore-cloning-submodules': str(ignore_cloning_submodules).lower()}
)
recipe.install()
main_repo_path = os.path.join(self.parts_directory_path, "test")
self.assertTrue(os.path.exists(main_repo_path))
submodule_repo_path = os.path.join(main_repo_path, 'dir2', 'test_erp5_submodule')
# Check if the folder exists
self.assertTrue(os.path.exists(main_repo_path))
# Check is there is anything in submodule repository path
self.assertNotEqual(bool(ignore_cloning_submodules), bool(os.listdir(submodule_repo_path)))
def test_ignore_cloning_submodules(self):
self.test_clone_submodules_by_default(ignore_cloning_submodules=True)
def test_fetch_submodules_with_main_repo(self):
"""
Test to check the fetch of submodules while fetching main repo. Updating
should udpate the main repo as well as submodule repo if the reference of
submodule in main repo has been udpated.
"""
recipe = self.makeGitCloneRecipe(
{'repository': GIT_REPOSITORY_WITH_SUBMODULES}
)
recipe.install()
main_repo_path = os.path.join(self.parts_directory_path, "test")
self.assertTrue(os.path.exists(main_repo_path))
submodule_repo_path = os.path.join(main_repo_path, 'dir2', 'test_erp5_submodule')
# Check if the submodule is not empty
self.assertTrue(os.listdir(submodule_repo_path))
# Get the head commit of the submodule repo
head_commit_submodule_before_fetch = check_output(['git', 'rev-parse',
'HEAD'], cwd=submodule_repo_path).strip()
# Now, let's update the main repo as well as submodule repository.
# Updating the repo will fetch the updated branch but doesn't checkout
# to the updated master branch.
recipe.update()
head_commit_after_udpate_before_checkout = check_output(['git', 'submodule',
'status', submodule_repo_path],
cwd=main_repo_path).split()[0]
# Checkout the submodule repository and get the head commit
check_call(['git', 'checkout', 'master'], cwd=submodule_repo_path)
head_commit_after_update_after_checkout = check_output(['git', 'rev-parse',
'HEAD'], cwd=submodule_repo_path).strip()
# Make another git clone of submodule and check the HEAD of the repo.
submodule_recipe = self.makeGitCloneRecipe(
{'repository': GIT_SUBMODULE_REPOSITORY}
)
submodule_recipe.install()
# Check the HEAD of the submodule
head_commit = check_output(['git', 'rev-parse', 'HEAD'],
cwd=main_repo_path).strip()
self.assertNotEqual(head_commit_submodule_before_fetch, head_commit)
self.assertNotEqual(head_commit_after_udpate_before_checkout, head_commit)
self.assertEqual(head_commit_after_update_after_checkout, head_commit)
def test_suite():
suite = unittest.TestSuite((
doctest.DocFileSuite(
......
......@@ -145,7 +145,8 @@ class Recipe(object):
self.git_command = 'git'
self.sparse = options.get('sparse-checkout', '').strip()
# Set boolean values
for key in ('develop', 'shared', 'use-cache', 'ignore-ssl-certificate'):
for key in ('develop', 'shared', 'use-cache', 'ignore-ssl-certificate',
'ignore-cloning-submodules'):
setattr(self, key.replace('-', '_'), options.get(key, '').lower() in TRUE_VALUES)
if self.shared:
self.use_cache = False
......@@ -213,6 +214,13 @@ class Recipe(object):
if config and self.use_cache:
raise NotImplementedError
if not self.ignore_cloning_submodules:
# `--recurse-submodules` to the git clone command will automatically
# initialize and update each submodule in the repository.
config.append('submodule.recurse=true')
git_clone_command.append('--recurse-submodules')
for config in config:
git_clone_command += '--config', config
......@@ -274,7 +282,15 @@ class Recipe(object):
call([self.git_command, 'rev-parse', '--verify', self.revision],
cwd=self.location) == 0
if not revision_already_fetched:
check_call([self.git_command, 'fetch', '--all'], cwd=self.location)
# With --recurse-submodules, it will fetch the updated branches of the
# submodules as well as of the main repo. It will remain in a detached
# head old state
# NOTE: It won't checkout to the updated master/main-branch
check_call([self.git_command, 'fetch', '--recurse-submodules', '--all'],
cwd=self.location)
# Also update the submodule directory
check_call([self.git_command, 'submodule', 'update', '--remote'],
cwd=self.location)
# If develop parameter is set, don't reset/update.
# Otherwise, reset --hard
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment