Repository: gitpython-developers/GitPython
Pull request #1280 (2021-06-30 09:48:41)

Added clone multi_options to Submodule
The purpose of the change is to add multiple_options for clone in Submodule simmilar as it is done in the Repo.clone().




Patch:
diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py
index cbf6cd0d..f0b8babc 100644
--- a/git/objects/submodule/base.py
+++ b/git/objects/submodule/base.py
@@ -316,7 +316,8 @@ class Submodule(IndexObject, IterableObj, Traversable):
     #{ Edit Interface
 
     @classmethod
-    def add(cls, repo, name, path, url=None, branch=None, no_checkout=False, depth=None, env=None):
+    def add(cls, repo, name, path, url=None, branch=None, no_checkout=False, depth=None, env=None,
+            clone_multi_options=None):
         """Add a new submodule to the given repository. This will alter the index
         as well as the .gitmodules file, but will not create a new commit.
         If the submodule already exists, no matter if the configuration differs
@@ -349,6 +350,8 @@ class Submodule(IndexObject, IterableObj, Traversable):
             and is defined in `os.environ`, value from `os.environ` will be used.
             If you want to unset some variable, consider providing empty string
             as its value.
+        :param clone_multi_options: A list of Clone options. Please see ``git.repo.base.Repo.clone``
+            for details.
         :return: The newly created submodule instance
         :note: works atomically, such that no change will be done if the repository
             update fails for instance"""
@@ -415,6 +418,8 @@ class Submodule(IndexObject, IterableObj, Traversable):
                     kwargs['depth'] = depth
                 else:
                     raise ValueError("depth should be an integer")
+            if clone_multi_options:
+                kwargs['multi_options'] = clone_multi_options
 
             # _clone_repo(cls, repo, url, path, name, **kwargs):
             mrepo = cls._clone_repo(repo, url, path, name, env=env, **kwargs)
@@ -449,7 +454,7 @@ class Submodule(IndexObject, IterableObj, Traversable):
         return sm
 
     def update(self, recursive=False, init=True, to_latest_revision=False, progress=None, dry_run=False,
-               force=False, keep_going=False, env=None):
+               force=False, keep_going=False, env=None, clone_multi_options=None):
         """Update the repository of this submodule to point to the checkout
         we point at with the binsha of this instance.
 
@@ -480,6 +485,8 @@ class Submodule(IndexObject, IterableObj, Traversable):
             and is defined in `os.environ`, value from `os.environ` will be used.
             If you want to unset some variable, consider providing empty string
             as its value.
+        :param clone_multi_options:  list of Clone options. Please see ``git.repo.base.Repo.clone``
+            for details. Only take effect with `init` option.
         :note: does nothing in bare repositories
         :note: method is definitely not atomic if recurisve is True
         :return: self"""
@@ -546,7 +553,8 @@ class Submodule(IndexObject, IterableObj, Traversable):
                 progress.update(BEGIN | CLONE, 0, 1, prefix + "Cloning url '%s' to '%s' in submodule %r" %
                                 (self.url, checkout_module_abspath, self.name))
                 if not dry_run:
-                    mrepo = self._clone_repo(self.repo, self.url, self.path, self.name, n=True, env=env)
+                    mrepo = self._clone_repo(self.repo, self.url, self.path, self.name, n=True, env=env,
+                                             multi_options=clone_multi_options)
                 # END handle dry-run
                 progress.update(END | CLONE, 0, 1, prefix + "Done cloning to %s" % checkout_module_abspath)
 


Test patch:
diff --git a/test/test_submodule.py b/test/test_submodule.py
index eb821b54..85191a89 100644
--- a/test/test_submodule.py
+++ b/test/test_submodule.py
@@ -9,6 +9,7 @@ from unittest import skipIf
 import git
 from git.cmd import Git
 from git.compat import is_win
+from git.config import GitConfigParser, cp
 from git.exc import (
     InvalidGitRepositoryError,
     RepositoryDirtyError
@@ -945,3 +946,68 @@ class TestSubmodule(TestBase):
         sm_depth = 1
         sm = parent.create_submodule(sm_name, sm_name, url=self._small_repo_url(), depth=sm_depth)
         self.assertEqual(len(list(sm.module().iter_commits())), sm_depth)
+
+    @with_rw_directory
+    def test_update_clone_multi_options_argument(self, rwdir):
+        #Arrange
+        parent = git.Repo.init(osp.join(rwdir, 'parent'))
+        sm_name = 'foo'
+        sm_url = self._small_repo_url()
+        sm_branch = 'refs/heads/master'
+        sm_hexsha = git.Repo(self._small_repo_url()).head.commit.hexsha
+        sm = Submodule(parent, bytes.fromhex(sm_hexsha), name=sm_name, path=sm_name, url=sm_url,
+                       branch_path=sm_branch)
+
+        #Act
+        sm.update(init=True, clone_multi_options=['--config core.eol=true'])
+
+        #Assert
+        sm_config = GitConfigParser(file_or_files=osp.join(parent.git_dir, 'modules', sm_name, 'config'))
+        self.assertTrue(sm_config.get_value('core', 'eol'))
+
+    @with_rw_directory
+    def test_update_no_clone_multi_options_argument(self, rwdir):
+        #Arrange
+        parent = git.Repo.init(osp.join(rwdir, 'parent'))
+        sm_name = 'foo'
+        sm_url = self._small_repo_url()
+        sm_branch = 'refs/heads/master'
+        sm_hexsha = git.Repo(self._small_repo_url()).head.commit.hexsha
+        sm = Submodule(parent, bytes.fromhex(sm_hexsha), name=sm_name, path=sm_name, url=sm_url,
+                       branch_path=sm_branch)
+
+        #Act
+        sm.update(init=True)
+
+        #Assert
+        sm_config = GitConfigParser(file_or_files=osp.join(parent.git_dir, 'modules', sm_name, 'config'))
+        with self.assertRaises(cp.NoOptionError):
+            sm_config.get_value('core', 'eol')
+
+    @with_rw_directory
+    def test_add_clone_multi_options_argument(self, rwdir):
+        #Arrange
+        parent = git.Repo.init(osp.join(rwdir, 'parent'))
+        sm_name = 'foo'
+
+        #Act
+        Submodule.add(parent, sm_name, sm_name, url=self._small_repo_url(),
+                      clone_multi_options=['--config core.eol=true'])
+
+        #Assert
+        sm_config = GitConfigParser(file_or_files=osp.join(parent.git_dir, 'modules', sm_name, 'config'))
+        self.assertTrue(sm_config.get_value('core', 'eol'))
+
+    @with_rw_directory
+    def test_add_no_clone_multi_options_argument(self, rwdir):
+        #Arrange
+        parent = git.Repo.init(osp.join(rwdir, 'parent'))
+        sm_name = 'foo'
+
+        #Act
+        Submodule.add(parent, sm_name, sm_name, url=self._small_repo_url())
+
+        #Assert
+        sm_config = GitConfigParser(file_or_files=osp.join(parent.git_dir, 'modules', sm_name, 'config'))
+        with self.assertRaises(cp.NoOptionError):
+            sm_config.get_value('core', 'eol')