Repository: gitpython-developers/GitPython
Pull request #413 (2016-04-18 09:19:00)

Support repeated kwargs
Some Git command line options are allowed to be repeated multiple times. Examples of this are the -C flag which may occur more than once to "strengthen" its effect, or the -L flag on Git blames, to select
multiple blocks of lines to blame.

    $ git diff -C -C HEAD~1 HEAD
    $ git blame -L 1-3 -L 12-18 HEAD -- somefile.py

This patch supports passing a list/tuple as the value part for kwargs, so that the generated Git command contain the repeated options.


Patch:
diff --git a/git/cmd.py b/git/cmd.py
index 7bd94e4d..e4e3d6da 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -764,23 +764,31 @@ class Git(LazyMixin):
         finally:
             self.update_environment(**old_env)
 
+    def transform_kwarg(self, name, value, split_single_char_options):
+        if len(name) == 1:
+            if value is True:
+                return ["-%s" % name]
+            elif type(value) is not bool:
+                if split_single_char_options:
+                    return ["-%s" % name, "%s" % value]
+                else:
+                    return ["-%s%s" % (name, value)]
+        else:
+            if value is True:
+                return ["--%s" % dashify(name)]
+            elif type(value) is not bool:
+                return ["--%s=%s" % (dashify(name), value)]
+        return []
+
     def transform_kwargs(self, split_single_char_options=True, **kwargs):
         """Transforms Python style kwargs into git command line options."""
         args = list()
         for k, v in kwargs.items():
-            if len(k) == 1:
-                if v is True:
-                    args.append("-%s" % k)
-                elif type(v) is not bool:
-                    if split_single_char_options:
-                        args.extend(["-%s" % k, "%s" % v])
-                    else:
-                        args.append("-%s%s" % (k, v))
+            if isinstance(v, (list, tuple)):
+                for value in v:
+                    args += self.transform_kwarg(k, value, split_single_char_options)
             else:
-                if v is True:
-                    args.append("--%s" % dashify(k))
-                elif type(v) is not bool:
-                    args.append("--%s=%s" % (dashify(k), v))
+                args += self.transform_kwarg(k, v, split_single_char_options)
         return args
 
     @classmethod


Test patch:
diff --git a/git/test/test_git.py b/git/test/test_git.py
index 3e3e21e4..00592b88 100644
--- a/git/test/test_git.py
+++ b/git/test/test_git.py
@@ -70,6 +70,10 @@ class TestGit(TestBase):
         assert_equal(["--max-count"], self.git.transform_kwargs(**{'max_count': True}))
         assert_equal(["--max-count=5"], self.git.transform_kwargs(**{'max_count': 5}))
 
+        # Multiple args are supported by using lists/tuples
+        assert_equal(["-L", "1-3", "-L", "12-18"], self.git.transform_kwargs(**{'L': ('1-3', '12-18')}))
+        assert_equal(["-C", "-C"], self.git.transform_kwargs(**{'C': [True, True]}))
+
         # order is undefined
         res = self.git.transform_kwargs(**{'s': True, 't': True})
         assert ['-s', '-t'] == res or ['-t', '-s'] == res