From d2c80745b961e8cd20870f19a83b49daaaf0f966 Mon Sep 17 00:00:00 2001 From: Piotr Babij Date: Tue, 3 Oct 2017 17:16:48 +0200 Subject: [PATCH] 648 max_chunk_size can be now set to control output_stream behavior --- git/cmd.py | 19 ++++++++++++------- git/test/test_repo.py | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/git/cmd.py b/git/cmd.py index 0f797e239..54537a41d 100644 --- a/git/cmd.py +++ b/git/cmd.py @@ -44,10 +44,10 @@ ) -execute_kwargs = {'istream', 'with_extended_output', 'with_exceptions', - 'as_process', 'stdout_as_string', 'output_stream', - 'with_stdout', 'kill_after_timeout', 'universal_newlines', - 'shell', 'env'} +execute_kwargs = {'istream', 'with_extended_output', + 'with_exceptions', 'as_process', 'stdout_as_string', + 'output_stream', 'with_stdout', 'kill_after_timeout', + 'universal_newlines', 'shell', 'env', 'max_chunk_size'} log = logging.getLogger(__name__) log.addHandler(logging.NullHandler()) @@ -174,8 +174,6 @@ def __setstate__(self, d): dict_to_slots_and__excluded_are_none(self, d, excluded=self._excluded_) # CONFIGURATION - # The size in bytes read from stdout when copying git's output to another stream - max_chunk_size = io.DEFAULT_BUFFER_SIZE git_exec_name = "git" # default that should work on linux and windows @@ -597,6 +595,7 @@ def execute(self, command, universal_newlines=False, shell=None, env=None, + max_chunk_size=io.DEFAULT_BUFFER_SIZE, **subprocess_kwargs ): """Handles executing the command on the shell and consumes and returns @@ -642,6 +641,11 @@ def execute(self, command, :param env: A dictionary of environment variables to be passed to `subprocess.Popen`. + + :param max_chunk_size: + Maximum number of bytes in one chunk of data passed to the output_stream in + one invocation of write() method. If the given number is not positive then + the default value is used. :param subprocess_kwargs: Keyword arguments to be passed to subprocess.Popen. Please note that @@ -788,7 +792,8 @@ def _kill_process(pid): stderr_value = stderr_value[:-1] status = proc.returncode else: - stream_copy(proc.stdout, output_stream, self.max_chunk_size) + max_chunk_size = max_chunk_size if max_chunk_size and max_chunk_size > 0 else io.DEFAULT_BUFFER_SIZE + stream_copy(proc.stdout, output_stream, max_chunk_size) stdout_value = output_stream stderr_value = proc.stderr.read() # strip trailing "\n" diff --git a/git/test/test_repo.py b/git/test/test_repo.py index 97eac4aeb..8b43051ec 100644 --- a/git/test/test_repo.py +++ b/git/test/test_repo.py @@ -5,6 +5,7 @@ # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php import glob +import io from io import BytesIO import itertools import os @@ -220,6 +221,22 @@ def test_clone_from_pathlib(self, rw_dir): Repo.clone_from(original_repo.git_dir, pathlib.Path(rw_dir) / "clone_pathlib") + @with_rw_repo('HEAD') + def test_max_chunk_size(self, repo): + class TestOutputStream(object): + def __init__(self, max_chunk_size): + self.max_chunk_size = max_chunk_size + + def write(self, b): + assert_true(len(b) <= self.max_chunk_size) + + for chunk_size in [16, 128, 1024]: + repo.git.status(output_stream=TestOutputStream(chunk_size), max_chunk_size=chunk_size) + + repo.git.log(n=100, output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE), max_chunk_size=None) + repo.git.log(n=100, output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE), max_chunk_size=-10) + repo.git.log(n=100, output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE)) + def test_init(self): prev_cwd = os.getcwd() os.chdir(tempfile.gettempdir())