summaryrefslogtreecommitdiff
path: root/lib/git
diff options
context:
space:
mode:
Diffstat (limited to 'lib/git')
-rw-r--r--lib/git/cmd.py46
-rw-r--r--lib/git/objects/commit.py14
-rw-r--r--lib/git/repo.py20
3 files changed, 53 insertions, 27 deletions
diff --git a/lib/git/cmd.py b/lib/git/cmd.py
index 940e35d1..867baee7 100644
--- a/lib/git/cmd.py
+++ b/lib/git/cmd.py
@@ -13,7 +13,7 @@ from errors import GitCommandError
GIT_PYTHON_TRACE = os.environ.get("GIT_PYTHON_TRACE", False)
execute_kwargs = ('istream', 'with_keep_cwd', 'with_extended_output',
- 'with_exceptions', 'with_raw_output')
+ 'with_exceptions', 'with_raw_output', 'as_process')
extra = {}
if sys.platform == 'win32':
@@ -34,6 +34,35 @@ class Git(object):
of the command to stdout.
Set its value to 'full' to see details about the returned values.
"""
+
+ class AutoInterrupt(object):
+ """
+ Kill/Interrupt the stored process instance once this instance goes out of scope. It is
+ used to prevent processes piling up in case iterators stop reading.
+ Besides all attributes are wired through to the contained process object
+ """
+ __slots__= "proc"
+
+ def __init__(self, proc ):
+ self.proc = proc
+
+ def __del__(self):
+ # did the process finish already so we have a return code ?
+ if self.proc.poll() is not None:
+ return
+
+ # try to kill it
+ try:
+ os.kill(self.proc.pid, 2) # interrupt signal
+ except AttributeError:
+ # try windows
+ subprocess.call(("TASKKILL", "/T", "/PID", self.proc.pid))
+ # END exception handling
+
+ def __getattr__(self, attr):
+ return getattr(self.proc, attr)
+
+
def __init__(self, git_dir=None):
"""
Initialize this instance with:
@@ -70,6 +99,7 @@ class Git(object):
with_extended_output=False,
with_exceptions=True,
with_raw_output=False,
+ as_process=False
):
"""
Handles executing the command on the shell and consumes and returns
@@ -96,6 +126,16 @@ class Git(object):
``with_raw_output``
Whether to avoid stripping off trailing whitespace.
+
+ ``as_process``
+ Whether to return the created process instance directly from which
+ streams can be read on demand. This will render with_extended_output,
+ with_exceptions and with_raw_output ineffective - the caller will have
+ to deal with the details himself.
+ It is important to note that the process will be placed into an AutoInterrupt
+ wrapper that will interrupt the process once it goes out of scope. If you
+ use the command in iterators, you should pass the whole process instance
+ instead of a single stream.
Returns::
@@ -127,7 +167,11 @@ class Git(object):
**extra
)
+ if as_process:
+ return self.AutoInterrupt(proc)
+
# Wait for the process to return
+ status = 0
try:
stdout_value = proc.stdout.read()
stderr_value = proc.stderr.read()
diff --git a/lib/git/objects/commit.py b/lib/git/objects/commit.py
index f9245217..340686ea 100644
--- a/lib/git/objects/commit.py
+++ b/lib/git/objects/commit.py
@@ -142,26 +142,28 @@ class Commit(base.Object, Iterable):
Returns
iterator yielding Commit items
"""
- options = {'pretty': 'raw'}
+ options = {'pretty': 'raw', 'as_process' : True }
options.update(kwargs)
- output = repo.git.rev_list(ref, '--', path, **options)
- return cls._iter_from_stream(repo, iter(output.splitlines(False)))
+ # the test system might confront us with string values -
+ proc = repo.git.rev_list(ref, '--', path, **options)
+ return cls._iter_from_process(repo, proc)
@classmethod
- def _iter_from_stream(cls, repo, stream):
+ def _iter_from_process(cls, repo, proc):
"""
Parse out commit information into a list of Commit objects
``repo``
is the Repo
- ``stream``
- output stream from the git-rev-list command (raw format)
+ ``proc``
+ git-rev-list process instance (raw format)
Returns
iterator returning Commit objects
"""
+ stream = proc.stdout
for line in stream:
id = line.split()[1]
assert line.split()[0] == "commit"
diff --git a/lib/git/repo.py b/lib/git/repo.py
index 0dd776f6..d5dab242 100644
--- a/lib/git/repo.py
+++ b/lib/git/repo.py
@@ -347,26 +347,6 @@ class Repo(object):
return root
- def log(self, commit='master', path=None, **kwargs):
- """
- The Commit for a treeish, and all commits leading to it.
-
- ``kwargs``
- keyword arguments specifying flags to be used in git-log command,
- i.e.: max_count=1 to limit the amount of commits returned
-
- Returns
- ``git.Commit[]``
- """
- options = {'pretty': 'raw'}
- options.update(kwargs)
- arg = [commit, '--']
- if path:
- arg.append(path)
- commits = self.git.log(*arg, **options)
- print commits.splitlines(False)
- return list(Commit._iter_from_stream(self, iter(commits.splitlines())))
-
def diff(self, a, b, *paths):
"""
The diff from commit ``a`` to commit ``b``, optionally restricted to the given file(s)